MySQL 8.0升级后SQL变慢主因是优化器“重新认识数据”:统计信息陈旧(last_update滞后)、optimizer_switch默认启用hash_join/skip_scan等新特性导致误判、cost_model对排序更敏感引发filesort/temporary;需对比EXPLAIN的type/rows/Extra变化,及时ANALYZE TABLE并按需更新直方图。

执行计划变动不是SQL写错了,而是MySQL 8.0的优化器“换脑子”了——统计信息没更新、optimizer_switch默认开关变了、cost_model对排序更较真,三者叠加导致它重新估算索引价值和访问路径。
为什么EXPLAIN里type从ref变成ALL、rows暴涨几倍?
这是最典型的信号:优化器误判了索引选择性。根本原因往往是INNODB_TABLESTATS.last_update时间还卡在升级前,而innodb_stats_auto_recalc=ON只对单次变更超10%行数的表触发,冷表、配置表、历史归档表基本不会自动刷新。
- 查确认:
SELECT last_update FROM INFORMATION_SCHEMA.INNODB_TABLESTATS WHERE TABLE_NAME = 'your_table',若早于升级时间,就是它 - 比失真度:
SHOW INDEX FROM your_table里的Cardinality值,和SELECT COUNT(DISTINCT col) FROM your_table差10倍以上,基本确认统计失效 - 别等自动更新:直接跑
ANALYZE TABLE your_table WITH SYNC强制同步更新,避免后台异步延迟
为什么突然冒出using_index_merge或hash_join?
MySQL 8.0.19+默认开启index_merge=on,8.0全版本默认开启hash_join=on。优化器会主动合并单列索引,或对JOIN启用哈希连接——但前提是它认为这样更快。如果统计不准、join_buffer_size太小、或者关联字段没索引,反而劣化。
- 定位是否启用:
EXPLAIN FORMAT=TREE输出里搜using_index_merge或hash_join - 临时验证:
SET SESSION optimizer_switch='index_merge=off,hash_join=off';再跑EXPLAIN看是否回归 - 别全局关:只关可疑项;长期方案优先检查
join_buffer_size、补索引、跑ANALYZE TABLE
为什么ORDER BY没索引却没报Using filesort,但查询变慢了?
8.0.20+已废弃max_length_for_sort_data,不再按字段长度切分排序模式。原来走索引有序扫描的查询,现在可能被优化器判定为“全字段排序内存不够”,直接退到磁盘filesort——尤其当SELECT *字段多、sort_buffer_size又偏小时。
- 真走索引排序的标志:
EXPLAIN的Extra列不含Using filesort - 临时绕过:
SELECT a,b,c代替SELECT *,看是否恢复毫秒级 - 根本解法:给
WHERE + ORDER BY字段建联合索引,例如WHERE a=1 ORDER BY b,c就建INDEX(a,b,c)
真正难处理的不是某个开关或参数,而是它们和统计信息、索引设计、内存配置耦合在一起——关一个hash_join可能缓解症状,但不更新INNODB_TABLESTATS,下一次范围查询照样崩。


















