谢谢大家。我在将数据库从 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'
重要的似乎是行列,对于 UPDATE 是 1198100,对于 SELECT 子查询是 1200537。这两个数字都非常接近两个引用表中的总行数(两者均为 1207744)。所以它似乎对两者的行扫描都进行了整行,我不明白为什么。完全相同的查询在 MySQL 5.5 中运行良好。我希望这个解决方案会有所帮助,但是将 'derived_merge=off' 传递给了 optimizer_switch 并且重新启动服务器并没有帮助。
我当然不希望这个查询超级快。它不一定是。之前的速度并不快(在 7200rpm 旋转磁盘上几分钟),但自从升级到 MySQL 5.7 之后,它似乎在宇宙热死之前的任何时候都不会完成,我宁愿不等长。有没有人有任何想法?无论是查询重写,还是 my.ini 设置或其他任何东西?
另外,如果我以任何方式违反协议或者我是否可以改进我的问题,请告诉我。正如我上面所说,这是我在这里的第一篇文章。
感谢您的时间。
编辑:我想了一会儿,这个解决方案看起来很有希望。显然,具有不同字符集/排序规则的表无法正确读取彼此的索引。我很确定一切都在latin1
,但认为值得确定。所以我明确地添加DEFAULT CHARSET=latin1
到我的所有CREATE TABLE
陈述中并添加CHARACTER SET latin1
到我的LOAD DATA INFILE
陈述中。可悲的是,没有改变。