Estou escrevendo um aplicativo que precisa liberar um grande número de atualizações no banco de dados por um longo período de tempo e fiquei paralisado para otimizar a consulta. Atualmente estou usando INSERT INTO ... VALUES (..), (..) ON DUPLICATE KEY UPDATE
, que funciona para agrupar todos os valores em uma consulta, mas executa incrivelmente lentamente em tabelas grandes. Na verdade, eu nunca preciso inserir linhas.
Outras abordagens que vi foram atualizar usando SET value = CASE WHEN...
(o que seria difícil de gerar devido à maneira como estou criando as consultas e não tenho certeza sobre o desempenho de CASE
centenas / milhares de chaves) e simplesmente concatenadas múltiplas atualizações. Um desses seria mais rápido que o meu método atual?
Me surpreende que, até onde eu saiba, não haja uma maneira idiomática e eficiente de fazer isso no MySQL. Se realmente não há uma maneira mais rápida do que ON DUPLICATE KEY
, valeria a pena mudar para o PostgreSQL e usar sua UPDATE FROM
sintaxe?
Quaisquer outras sugestões também são muito apreciadas!
Editar: aqui está uma das tabelas que são atualizadas com frequência. Removi os nomes das colunas por serem irrelevantes.
CREATE TABLE IF NOT EXISTS `table` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`a` bigint(20) unsigned NOT NULL DEFAULT '0',
`b` bigint(20) unsigned NOT NULL DEFAULT '0',
`c` enum('0','1','2') NOT NULL DEFAULT '0',
`d` char(32) NOT NULL,
-- trimmed --
PRIMARY KEY (`id`),
KEY `a` (`a`),
KEY `b` (`b`),
KEY `c` (`c`),
KEY `d` (`d`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Respostas:
Como você está usando
InnoDB
tabelas, a otimização mais óbvia seria agrupar váriosUPDATE
s em uma transação.Com
InnoDB
, sendo um motor transacional, você não pagar apenas para oUPDATE
próprio, mas também para toda a sobrecarga transacional: gerir o buffer de transação, o log de transações, lavando o log para o disco.Se você estiver logicamente confortável com a ideia, tente agrupar 100-1000
UPDATE
s de cada vez, sempre agrupados da seguinte maneira:Possíveis desvantagens:
UPDATE
s, portanto, também pode querer ter um tempo limitefonte