MySQL 5.7 升级至 8.0 后,optimizer_switch 至少 12 项默认值变化,需导出比对 baseline、逐项验证开关影响,并结合统计信息、索引设计与 sql_mode 综合调优。

对比 optimizer_switch 前后值,别只看“on/off”列表
MySQL 5.7 升级到 8.0 后,optimizer_switch 中有至少 12 项子开关的默认值发生了变化,不是所有都显式写在配置文件里。直接执行 SHOW VARIABLES LIKE 'optimizer_switch'; 看到的是一长串逗号分隔的 key=value,但容易忽略某一项被“静默关闭”——比如 mrr=off 在 5.7 是默认 on,8.0 却是 off;又比如 hash_join=on 在 8.0 才引入,旧版压根没有这项。
实操建议:
- 升级前在生产库导出完整值:
SELECT @@optimizer_switch;,存为 baseline.txt - 升级后立刻在测试/新生产库执行同样语句,用 diff 工具逐行比对,重点关注带
=off的项(尤其是mrr、use_index_extensions、derived_merge) - 不要依赖“看起来差不多”,
index_merge=on,index_merge_union=on和index_merge=on,index_merge_union=off可能导致联合索引完全不被选用
临时开启可疑开关验证执行计划是否恢复
发现某条慢查询在 8.0 上 EXPLAIN 显示 type=ALL、rows 暴涨,而 5.7 是 type=ref,大概率是优化器绕过了你原以为“够用”的索引组合。这时不是立刻改 SQL 或加索引,而是先用 SET SESSION optimizer_switch='mrr=on,use_index_extensions=on'; 临时打开几个高概率相关的开关,再跑一遍 EXPLAIN。
注意点:
解析 MySQL 8.0 的 DDL 脚本,并将表结构导出为 Excel 格式。适用于用户需将 MySQL 的 `CREATE TABLE` 语句转换为结构化的 Excel 文件场景,导出内容包含字段名、数据类型、长度及精度等信息。支持多张表的批量处理,每张表对应 Excel 中的一个独立工作表。适用于数据库文档编写、数据字典生成及模式分析等任务。
- 必须用
SESSION级别,避免影响其他连接;测试完记得重置(或新开连接) - 每次只开 1–2 个开关,否则无法归因。例如先试
mrr=on,没改善再试use_index_extensions=on - 若开启
hash_join=on后 JOIN 查询变快,说明旧版靠嵌套循环硬扛,新版有能力用哈希连接提速——但要注意内存消耗是否同步上涨
禁用 index_merge 可能反而让查询变快
8.0 默认开启 index_merge=on,听起来是好事,但它会让优化器尝试把多个单列索引“拼起来”用。实际中,这种策略常导致:走两个索引后做交集/并集,中间结果集膨胀,最终比单走一个复合索引还慢。你看到 Extra 里出现 Using intersect(...) 或 Using union(...) 就是信号。
验证方式:
- 执行
SET SESSION optimizer_switch='index_merge=off'; - 再跑
EXPLAIN,观察key是否切换回你预设的复合索引,rows是否明显下降 - 如果有效,长期方案不是关全局开关,而是删掉那些被 merge 的冗余单列索引,补上真正匹配 WHERE + ORDER BY 的复合索引(如
WHERE a=1 AND b>10 ORDER BY c→INDEX(a,b,c))
sql_mode 改变会间接干扰 optimizer_switch 生效逻辑
sql_mode 本身不控制执行计划,但它影响字段隐式转换行为,进而让优化器“看不见”索引。比如 8.0 默认含 STRICT_TRANS_TABLES,当 WHERE status = 1 对应的是 VARCHAR 字段时,5.7 可能容忍隐式转成数字去匹配索引,8.0 则可能放弃走索引、退化为全表扫描——这时你调 optimizer_switch 没用,因为根本没到优化器选路径那步。
排查动作:
- 查当前模式:
SELECT @@sql_mode;,确认是否含STRICT_TRANS_TABLES - 对慢查询中的等值条件,检查字段类型和传入值类型是否严格一致(尤其注意字符串型 ID、状态码)
- 临时去掉严格模式测试:
SET SESSION sql_mode=(SELECT REPLACE(@@sql_mode,'STRICT_TRANS_TABLES',''));,再看EXPLAIN是否恢复走索引
ANALYZE TABLE 没跑、innodb_stats_persistent 没开、复合索引没建全,执行计划照样崩。


















