使用SELECT子查询的UPDATE在MySQL 5.7上运行速度非常慢(但在5.5上运行正常)

时间:2016-09-14 03:47:15

标签: mysql sql mysql-5.7 mysql-dependent-subquery query-planner

提前谢谢大家。我在将数据库从MySQL 5.5升级到5.7时遇到了一个问题,让我完全和完全混淆了。升级不是使用mysqldump或类似的,而是使用几个非常长的SQL脚本从几个选项卡分隔的输入文件重建。特别是一个看似无害的查询(在存储过程中)一直给我带来麻烦,我无法解决原因:

UPDATE liverpool.master_person mp 
SET Link_Count = ( SELECT count(*) FROM liverpool.person_record pr
WHERE mp.Master_Person_ID = pr.Master_Person_ID ) - 1;

这看起来相当简单,但此查询中的EXPLAIN显示正在进行一些严重的行扫描:

# id | select_type          | table | partitions | type    | possible_keys | key                    | key_len | ref  | rows      | filtered | Extra
========================================================================================================================================================================
'1'  | 'UPDATE'             | 'mp'  | NULL       | 'index' | NULL          | 'PRIMARY'              | '4'     | NULL | '1198100' | '100.00' | NULL
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
'2'  | 'DEPENDENT SUBQUERY' | 'pr'  | NULL       | 'index' | NULL          | 'Master_Person_ID_IDX' | '17'    | NULL | '1200537' | '100.00' | 'Using where; Using index'

重要的事情似乎是rows列,UPDATE为1198100,SELECT子查询为1200537。这两个数字都非常接近两个引用表中的总行数(两者都为1207744)。所以它似乎是为两行的行扫描做了一整行,我不明白为什么。确切地说,相同的查询在MySQL 5.5中运行良好。我希望this解决方案有所帮助,但将'derived_merge = off'传递给optimizer_switch并重新启动服务器没有帮助。

我当然不希望这个查询超级快。它不一定是。它之前并不是那么快(在7200rpm旋转磁盘上几分钟),但自从升级到MySQL 5.7之后,似乎在宇宙热死之前的任何时候它都无法完成,我宁愿不等待长。那里有人有什么想法吗?是查询重写,还是my.ini设置或其他任何内容?

另外,如果我以任何方式违反协议或者我可以改进我的问题,请告诉我。正如我上面所说,这是我在这里的第一篇文章。

感谢您的时间。

编辑:我想了一下,this解决方案看起来很有希望。显然,具有不同字符集/校对的表无法正确读取彼此的索引。我非常确保所有内容都在latin1,但我认为值得确定。因此,我明确地将DEFAULT CHARSET=latin1添加到我的所有CREATE TABLE语句中,并将CHARACTER SET latin1添加到我的LOAD DATA INFILE语句中。可悲的是,没有变化。

1 个答案:

答案 0 :(得分:0)

尝试将查询重写为:

find /usr/local/nagios/var/spool/xidpe/ -type f -ctime +365 -delete