在MySQL中批处理UPDATE查询的最有效方法是什么?


10

我正在编写一个应用程序,该应用程序需要长时间刷新数据库的大量更新,而我一直沉迷于如何优化查询。目前,我正在使用INSERT INTO ... VALUES (..), (..) ON DUPLICATE KEY UPDATE,它可以将所有值批处理到一个查询中,但是在大型表上执行速度非常慢。我实际上从来不需要插入行。

我见过的其他方法是使用更新SET value = CASE WHEN...(由于我构建查询的方式而很难生成,并且我不确定CASE数百/数千个键的性能),并且只是多个连接更新。这些方法都比我目前的方法快吗?

据我所知,在MySQL中没有一种惯用的,有效的方法可以使我感到困惑。如果确实没有比更快的方法ON DUPLICATE KEY,是否值得切换到PostgreSQL并使用其UPDATE FROM语法?

任何其他建议也将不胜感激!

编辑:这是经常更新的表之一。由于它们不相关,因此我删除了列名。

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;

这是在测试机上而不是生产环境上,因此InnoDB不能完全正确地调整。我不确定INSERT FROM的工作方式,但是您所说的似乎正确。使用您要求的信息更新了问题。
jli 2012年

Answers:


14

由于您使用的是InnoDB表格,最明显的优化方法是将多个UPDATEs 分组为一个事务。

使用InnoDB,作为事务引擎,您不仅要为其UPDATE本身付费,而且还要为所有事务开销付费:管理事务缓冲区,事务日志,将日志刷新到磁盘。

如果您对这个想法在逻辑上感到满意,请尝试UPDATE一次将100-1000 s 分组,每次包裹如下:

START TRANSACTION;
UPDATE ...
UPDATE ...
UPDATE ...
UPDATE ...
COMMIT;

可能的缺点:

  • 一个错误将使整个事务崩溃(但很容易用代码修复)
  • 您可能需要等待很长时间才能累积1000 UPDATE秒,所以您可能还想超时
  • 您的应用程序代码更加复杂。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.