Velocidades de inserção para lotes grandes


10

Na minha inscrição, meus INSERTs parecem estar demorando uma grande parte do tempo. Eu tenho um grande número de objetos na memória (~ 40-50.000) que eu quero inserir em uma tabela.

Vamos pegar uma tabela de amostra

CREATE TABLE bill (
id BIGINT(20) PRIMARY KEY,
amount INT(11) DEFAULT 0,
bill_date DATETIME DEFAULT NOW(),
INDEX (bill_date)
) ENGINE=InnoDB

Tomando 3 linhas como meu tamanho de lote, a seguir estão as abordagens que eu poderia pensar para inserir

Abordagem 1 - construir e acionar 3 inserções brutas

INSERT INTO bill (amount, bill_date) VALUES (10, '2012-01-01 00:00:00');
INSERT INTO bill (amount, bill_date) VALUES (20, '2012-01-02 00:00:00');
INSERT INTO bill (amount, bill_date) VALUES (40, '2013-02-05 00:00:00');

Abordagem 2 - agrupar os valores em uma consulta

INSERT INTO bill (amount, bill_date) VALUES 
(10, '2012-01-01 00:00:00'),
(20, '2012-01-02 00:00:00'),
(40, '2013-02-05 00:00:00');

Abordagem 3 - dispare esta consulta 1 vez passando 6 parâmetros

INSERT INTO bill (amount, bill_date) VALUES 
(?, ?), (?, ?), (?, ?);

Abordagem 4 - Dispare esta consulta preparada 3 vezes, alterando os 2 parâmetros a cada vez

INSERT INTO bill (amount, bill_date) VALUES (?, ?);

Quaisquer outras abordagens são bem-vindas.

Minha pergunta é

Qual é a maneira mais rápida de fazer várias inserções em uma tabela?

Eu li este link no mysql insert speed e este guia para programação JDBC , mas não consigo chegar a uma conclusão.

O meu caso -

Atualmente, minha tabela possui ~ 20 colunas, a maioria delas números, com algumas varchar (60) e 1 coluna de texto. Mysql versão 5.5. Executando no INNODB e possui 1 índice nas chaves primárias Inteiras. Todas as consultas são executadas na transação.

Eu construo minhas consultas a partir de Java e uso o Spring JDBC para executar as consultas.

Atualmente, estou seguindo a Abordagem 3, que leva cerca de 10 segundos para 20.000 inserções em uma tabela vazia, sem incluir o tempo necessário para construir a consulta.

Para manter as coisas em perspectiva, são necessários 100-200 milis para buscar os dados da tabela.

Há algo que estou perdendo? Como faço para tornar as pastilhas mais rápidas?


Pergunta relacionada sobre Stack Overflow: MySQL e JDBC com rewriteBatchedStatements = true
Gord Thompson

Respostas:


3

Considere agrupar seus commits. Um tamanho de lote de 1024 é um bom tamanho inicial. Altere os tamanhos dos lotes até atingir o rendimento ideal.


1

Você testou ou seria possível descartar índices na (s) tabela (s) de banco de dados de destino em que está inserindo, insira-os em blocos em lotes menores (ideal como indicado acima) e, em seguida, reconstrua os índices nas tabelas de destino quando todas as inserções estiverem concluídas? Pode ser algo fácil o suficiente para testar para confirmar.


0

Algumas dicas de carregamento de dados em massa do documento mysql são possíveis úteis. https://dev.mysql.com/doc/refman/5.6/en/optimizing-innodb-bulk-data-loading.html

Você pode aumentar a velocidade da pastilha de algumas maneiras:

- turn off autocommit
- turn off unique check
- turn off foreign check

Espero que esta ajuda!


2
Se desativar as verificações de restrição (chave estrangeira exclusiva, ...), verifique se seus dados não os quebram ou se o banco de dados está em um estado inconsistente a partir desse ponto.
David Spillett
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.