Eu tenho cerca de 40 milhões de linhas em uma tabela MySQL e quero copiar esta tabela para outra tabela no mesmo banco de dados. Qual é a maneira mais eficiente de fazer isso? Quanto tempo levará (aprox.)?
mysql
insert
bulk-insert
Devashish Dixit
fonte
fonte
Respostas:
Suponha que você tenha
mydb.mytb
e queira criarmydb.mytbcopy
Eu tenho cinco (5) abordagens para fazer esta cópia
ABORDAGEM # 1
No
mysql
cliente, execute o seguinteABORDAGEM # 2
ABORDAGEM # 3
ABORDAGEM # 4
ABORDAGEM # 5
ANÁLISE
Se você deseja copiar
mydb.mytb
para uma tabela já existentemydb.mytbcopy
, e as duas tabelas possuem estruturas idênticas:ABORDAGEM # 6
Assim como o #APPROACH 1 , o #APPROACH 6 teria uma única transação de 40 milhões de linhas
ABORDAGEM # 7
Essa abordagem não descarta a tabela. Simplesmente gera os INSERTs
EPÍLOGO
Não posso fornecer uma estimativa de tempo, pois não conheço a composição do DB Server, a estrutura da tabela, o layout do índice e coisas assim.
DE UMA CHANCE !!!
fonte
As tabelas do InnoDB, diferentemente do MyISAM *, não podem ser "simplesmente copiadas", como parte de seu dicionário de dados (e potencialmente outras estruturas em que a tabela depende, como o buffer de mesclagem) estão localizadas na memória (se o servidor estiver em execução) e em o espaço de tabela comum / principal, também conhecido como arquivo grande chamado
ibdata1
.Se você estiver usando o Percona Server> = 5.1 ou MySQL> = 5.6, há suporte para espaços de tabela transportáveis, o que permite exportar e importar tabelas diretamente do sistema de arquivos. Aqui está o método para MySQL e Percona . Nos dois casos, é necessário que você tenha criado a tabela com a
innodb_file_per_table
opção e envolva o uso deDISCARD TABLESPACE/IMPORT TABLESPACE
e / ou Percona Xtrabakup (se desejar que a exportação seja feita on-line). Observe que o Percona Server ou o Xtrabakup não estão disponíveis para Windows.Este método será, falando em geral, tão rápido quanto copiar o arquivo usando os comandos do sistema de arquivos (cp, rsync).
Embora possa haver alguns casos em que isso possa funcionar no MySQL <5.6 (de maneira hacky) para restaurações, ele não funcionará para uma cópia da tabela. Nesses casos, uma maneira de fazer isso é usando o SQL :
Isso será o mais rápido que o InnoDB pode executar
Handler_read_rnd_next
eHandler_write
, uma vez por linha. Se você usar esse método, desabilite, pelo menos temporariamente, as opções de durabilidade e tenha um grande buffer pool e log de transações. Nessas circunstâncias, pode reduzir o tempo de importação, mas definitivamente não caberá totalmente na memória; portanto, espere muito tempo. Além disso, você está tentando importar linhas de 40 milhões em uma única transação, o que pode levar a problemas.Minha recomendação real, neste segundo caso, seria usar algo como pt-archiver , pois ele executará uma operação semelhante à que acabei de mencionar, mas será feita em "pedaços", evitando a sobrecarga transacional (pode ser não seja mais rápido, mas, no caso de uma falha, ele não tentará reverter a tabela inteira, levando uma eternidade). Para os tamanhos de dados mencionados, este é provavelmente o melhor caminho a percorrer.
Uma opção final seria exportar e importar usando o formato CSV (ou TSV) , com uma combinação de SELECT INTO OUTFILE / mysqldump e LOAD DATA / mysqlimport. Essa era uma opção muito comum se você precisasse de simultaneidade em certas versões antigas do mysql, pois o sql criava bloqueios maiores (não é mais verdade se feito corretamente). Como o mysqldump / import funciona apenas de maneira serializada, eu recomendaria que você pesquisasse opções para paralelizar isso, muito útil para tabelas grandes.
De qualquer forma, tente evitar várias frases SQL, pois será o seu gargalo mais importante se você executar muitas consultas diferentes (que precisam ser executadas, analisadas e otimizadas individualmente).
* As estruturas MyISAM não podem ser copiadas de maneira quente, mas é muito fácil sincronizá-las temporariamente com o disco
FTWRL
.fonte
mover dados de uma tabela para outra no esquema
create table your_table_name select * from old_schema_table;
fonte