Por que 'LOAD DATA INFILE' é mais rápido que as instruções INSERT normais?

22

Eu li um artigo que mencionou que podemos obter 60.000 inserções por segundo usando a LOAD DATA IN FILEinstrução que lê arquivos csv e insere os dados em um banco de dados.

Por que deveria diferir das pastilhas normais?

EDIT:
reduzi a viagem de ida e volta chamando apenas uma INSERTdeclaração:

INSERT INTO tblname
VALUES (NULL,2,'some text here0'),(NULL,2,'some text here1')
    ,(NULL,2,'some text here2'),(NULL,2,'some text here3')
    .....,(NULL,2,'some text here3000');

E isso?

ALH
fonte
Eu escrevi um artigo no Medium, comparando inserções estendidas vs LOAD DATA INFILE: inserções de alta velocidade com MySQL . Conclusão: você pode atingir 65% do desempenho do LOAD DATA INFILEuso de pastilhas estendidas. Eu tenho 240.000 inserções / segundo em hardware moderno.
Benjamin

Respostas:

26

LOAD DATA INFILE e INSERTs estendidos têm vantagens distintas.

LOAD DATA INFILE foi projetado para carregamento em massa de dados da tabela em uma única operação, juntamente com sinos e assobios para executar operações como:

  • Ignorando linhas iniciais
  • Ignorando colunas específicas
  • Transformando colunas específicas
  • Carregando colunas específicas
  • Lidando com problemas de chave duplicados

É necessária menos sobrecarga para analisar

Por outro lado, se você estiver importando apenas 100 linhas em vez de 1.000.000 de linhas, o INSERT estendido será sensato.

Observe que o mysqldump foi projetado em torno de INSERTs estendidos para levar o design da tabela junto com os dados, pois ele executa a injeção de centenas ou milhares de linhas por INSERT. LOAD DATA INFILE sempre cria uma dicomotia física entre o esquema e os dados.

Do ponto de vista do aplicativo, LOAD DATA INFILE também é mais insensível à alteração de esquema do que INSERTs estendidos.

Pode-se ir e voltar no bom, no ruim e no feio de usar LOAD DATA INFILE. Independentemente da técnica usada, você sempre deve definir o bulk_insert_buffer_size . Por quê?

De acordo com a documentação do MySQL em bulk_insert_buffer_size:

O MyISAM usa um cache especial em forma de árvore para tornar as inserções em massa mais rápidas para INSERT ... SELECT, INSERT ... VALUES (...), (...), ... e LOAD DATA INFILE ao adicionar dados a objetos não vazios tabelas. Essa variável limita o tamanho da árvore de cache em bytes por encadeamento. Definir como 0 desativa essa otimização. O valor padrão é 8 MB.

Durante anos, vi cliente após cliente não definir isso e deixá-lo em 8 MB. Então, quando eles decidem usar LOAD DATA INFILE ou importar o mysqldumps, eles podem sentir algo errado. Eu normalmente recomendo definir isso para um 256M moderado. Em alguns casos, 512 milhões.

Depois de ter um buffer INSERT em volume suficientemente grande, o uso de qualquer uma das técnicas é tornado acadêmico e resume-se à escolha pessoal. Para aplicativos em que você insere em massa apenas 100 linhas sob demanda, use INSERTs estendidos.

Com toda a sinceridade, dizer LOAD DATA INFILE é mais rápido do que as instruções INSERT normais são um tipo de instrução carregada, principalmente porque a configuração não é levada em consideração. Mesmo que você configure uma referência entre LOAD DATA INFILE e INSERTs estendidos com um bulk_insert_buffer_size adequado, os nanossegundos salvos na análise de cada linha só podem gerar resultados nominais, na melhor das hipóteses, para LOAD DATA INFILE.

Vá em frente e adicione isso ao my.cnf

[mysqld]
bulk_inset_buffer_size=256M

Você também pode configurá-lo apenas para sua sessão antes de iniciar INSERTs estendidos

SET bulk_insert_buffer_size= 1024 * 1024 * 256;

UPDATE 2012-07-19 14:58 EDT

Para manter as coisas em perspectiva, o buffer de inserção em massa é útil apenas para carregar tabelas MyISAM, não o InnoDB. Escrevi uma postagem mais recente sobre carregamento em massa InnoDB: Carregamento Mysql de infile preso aguardando no disco rígido

RolandoMySQLDBA
fonte
4

A maioria dos sistemas de gerenciamento de banco de dados possui um recurso de carregamento em massa para carregar grandes volumes de dados rapidamente. Uma INSERTdeclaração possui uma quantidade significativa de bagagem por declaração - bloqueio, demarcação de transação, verificações de integridade referenciais, alocação de recursos, E / S que deve ser feita por declaração.

As operações de inserção em massa agilizam o processo para que essas coisas tenham muito menos sobrecarga por linha. Um DBMS pode carregar em massa ordens de grandeza de dados mais rapidamente do que através de instruções de inserção.

ConcernedOfTunbridgeWells
fonte
3

A análise e execução de INSERTinstruções individuais carregam uma sobrecarga muito maior do que a divisão de um arquivo CSV em colunas e o carregamento direto.

Cada INSERTdeclaração deve ser analisada individualmente pelo mecanismo MySQL e verificada quanto à validade - isso consome recursos extras da CPU e também requer mais viagens de ida e volta ao servidor do cliente. Isso não precisa acontecer durante o carregamento em massa via LOAD DATA INFILE. Também há otimizações que podem ocorrer ao usar o LOAD DATA INFILEcarregamento em uma tabela vazia. Veja este link para mais informações.

Philᵀᴹ
fonte
veja a parte EDIT da minha pergunta.
ALH20
Observe que não há sobrecarga de análise ao usar instruções preparadas.
Benjamin Benjamin