【问题标题】:MySQL update takes too longMySQL 更新耗时过长
【发布时间】:2016-11-25 21:10:53
【问题描述】:

我们在一个表中有超过 2000 万条记录,我们尝试更新 3K 条记录,但花费了 7 多分钟并且没有完成,因此终止了查询。

示例查询,

UPDATE TABLE_A
SET STATUS = 'PENDING'
WHERE ID IN (
  SELECT ID
  FROM TMP_TABLE_A_STATUS_FIX
);   /*took more than 7 mins and didn't complete even after that*/

我们在临时表 TMP_TABLE_A_STATUS_FIX(只有 3K 条记录)中收集了所有需要更新的 id。

由于上述查询耗时过长,我们单独更新如下,

UPDATE TABLE_A SET STATUS = 'PENDING' WHERE ID = 1;
UPDATE TABLE_A SET STATUS = 'PENDING' WHERE ID = 2;
UPDATE TABLE_A SET STATUS = 'PENDING' WHERE ID = 3;
.
.
.
UPDATE TABLE_A SET STATUS = 'PENDING' WHERE ID = 2999;
UPDATE TABLE_A SET STATUS = 'PENDING' WHERE ID = 3000; /*updated all 3K recordds in 0.00 secs*/

我真的不明白IN 查询有什么问题。

有人可以解释在 where 子句中包含 INin 的更新中有什么问题以及为什么即使在 7 分钟后也没有完成?

注意 - TABLE_A 中的 ID 是主键和它的索引。 TABLE_A 中的 STATUS 也被索引。我们删除了 STATUS 的索引,因为我们认为更新索引列可能会由于索引重组而需要一些时间,但这并没有帮助。

【问题讨论】:

  • ID 列有索引吗?没有大量记录的索引表由于大量的 IO 操作来过滤受影响的记录需要太多时间。
  • @Adil,是的,我们确实有索引,更新了问题。
  • 我的猜测是,在每个 UPDATE 调用中,您的查询会检查它当前检查的 ID 是否与 TMP_TABLE_A_STATUS_FIX 表中的 ID 匹配,它通过检查每个 @ TMP_TABLE_A_STATUS_FIX 表中的 987654330@。那是 3k * 300 万次操作。
  • IN 是一个已识别的数据库,如果我们从数据库中处理大量数据,则需要很长时间才能处理,请使用其他方式,例如存在..
  • 此处讨论了类似问题:stackoverflow.com/questions/5018284/…

标签: mysql sql database relational-database


【解决方案1】:

使用 in 子句的 Insetad 尝试使用内部连接

UPDATE TABLE_A
INNER JOIN TMP_TABLE_A_STATUS_FIX on TABLE_A.ID = TMP_TABLE_A_STATUS_FIX .ID
SET STATUS = 'PENDING';

【讨论】:

  • 学分也应归于@Tyler 和#Rocherlee 的cmets。
  • @whoami ..我没有看到评论..但是..我看看
  • @whoami 感谢#Tyler 和#Rocherlee 的正确索引总是有用的
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-10-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-18
  • 2016-11-12
相关资源
最近更新 更多