Mysql更新性能突然变得糟糕透了
MySQL 5.1,Ubuntu 10.10 64位,Linode虚拟机 所有表都是InnoDB 我们的一台生产机器使用包含31个相关表的MySQL数据库。在一个表中,有一个包含显示值的字段,根据条件,显示值每天可能更改数次 这些对显示值的更改在一天中的使用时间内缓慢应用。脚本定期运行并检查一些可能导致更改的条件,并在满足条件时更新显示值。但是,这种延迟方法并不能捕获所有可能的场景,在这些场景中,显示值应该更新,以便在工作时间内将后台进程负载保持在最小 每晚一次,脚本清除存储在表中的所有显示值并重新计算它们,从而捕获所有可能的更改。这是一个更昂贵的操作 这一切已经持续运行了大约6个月。三天前,夜间脚本的运行时间突然从平均40秒增加到11分钟 存储数据的总体比例没有显著变化 我已经尽我所能进行了调查,脚本中突然运行较慢的部分是写入新显示值的最后一条update语句。给定行的(INT(11))id和新的显示值(也是INT),每行执行一次 有趣的是,清除所有以前的值的过程如下所示:Mysql更新性能突然变得糟糕透了,mysql,ubuntu-10.10,Mysql,Ubuntu 10.10,MySQL 5.1,Ubuntu 10.10 64位,Linode虚拟机 所有表都是InnoDB 我们的一台生产机器使用包含31个相关表的MySQL数据库。在一个表中,有一个包含显示值的字段,根据条件,显示值每天可能更改数次 这些对显示值的更改在一天中的使用时间内缓慢应用。脚本定期运行并检查一些可能导致更改的条件,并在满足条件时更新显示值。但是,这种延迟方法并不能捕获所有可能的场景,在这些场景中,显示值应该更新,以便在工作时间内将后台进程负载保持在最小 每晚一次,脚本清除存储在表中的所有显示值并
update `table` set `display_value` = null
这句话的速度仍然和往常一样
显示值
字段未编制索引<代码>id是主键。表
中还有4个外键在执行过程中任何时候都不会被修改
最后一个曲线球:如果我将此模式转储到测试VM,并执行相同的脚本,它将在40秒而不是11分钟内运行。我没有尝试在生产机器上重建模式,因为这不是一个长期的解决方案,我想了解这里发生了什么
我的索引有问题吗?在同一行上进行了数千次更新后,它们是否变得粗糙
更新 通过在模式上运行优化,我能够完全解决这个问题。由于InnoDB不支持optimize,因此强制进行了重建,并解决了问题。也许我的索引被破坏了
mysqlcheck -A -o -u <user> -p
mysqlcheck-A-o-u-p
有可能UPDATE
语句不会在id
上使用索引,但是,对于像您这样的查询,这是非常不可能的(如果可能的话)
您的表是否有可能被长时间运行的并发查询/DML
锁定?桌子使用哪种引擎
此外,逐个记录更新表记录也没有效率。您可以批量将值加载到临时表中,并使用单个命令更新主表:
CREATE TEMPORARY TABLE tmp_display_values (id INT NOT NULL PRIMARY KEY, new_display_value INT);
INSERT
INTO tmp_display_values
VALUES
(?, ?),
(?, ?),
…;
UPDATE `table` dv
JOIN tmp_display_values t
ON dv.id = t.id
SET dv.new_display_value = t.new_display_value;
谢谢你的回复。所有表都是InnoDB。在执行时,不应运行其他查询。我们的客户群都处于休眠状态,没有其他自动化流程在运行。我知道效率低下,直到现在才考虑到这一点。我能够通过重建模式来解决问题,但您关于性能的观点仍然完全有效,因此我将您的回答标记为解决方案。谢谢经过周末的进一步测试,我一直无法找出突然的变化。与以前的历史相比,此脚本的执行时间仍然太长。我甚至完全重启了生产机器。
CREATE TEMPORARY TABLE tmp_display_values (id INT NOT NULL PRIMARY KEY, new_display_value INT);
INSERT
INTO tmp_display_values
VALUES
(?, ?),
(?, ?),
…;
UPDATE `table` dv
JOIN tmp_display_values t
ON dv.id = t.id
SET dv.new_display_value = t.new_display_value;