mysql 8.0隐式转换不慢但会导致执行计划崩坏:strict_trans_tables下优化器放弃索引使type退化为all;json字段类型不匹配引发全表扫描;order by类型不一致触发filesort;根治需统一类型、建合适索引并紧盯explain。

隐式转换在MySQL 8.0里不会“变慢”,但会直接失败或绕过索引——性能问题本质是执行计划崩了,不是函数变慢。
为什么EXPLAIN里type从ref变成ALL?
5.7对隐式类型转换(比如WHERE user_id = '123'查INT字段)常容忍并自动转,还能走索引;8.0默认开启STRICT_TRANS_TABLES,部分场景下不转、不报错,但优化器直接放弃该索引路径,导致type退化为ALL,rows暴涨。
- 典型现象:SQL没改,升级后慢查询日志里
Rows_examined从100跳到10万 - 验证方式:对慢SQL跑
EXPLAIN FORMAT=TREE,看是否出现Using where; Full scan - 快速定位:用
SELECT @@sql_mode确认是否含STRICT_TRANS_TABLES,再查SHOW CREATE TABLE确认字段类型与传参是否严格匹配
JSON字段上的隐式转换最危险
8.0对JSON字段的校验更重,WHERE JSON_CONTAINS(meta, '123')这种写法——字符串'123'和JSON里的数字123类型不一致,不会自动转,而是全表解析每个JSON blob,Rows_examined等于表总行数。
- 错误写法:
WHERE JSON_CONTAINS(data, '"admin"')→ 字符串字面量,但JSON里存的是"admin"还是admin(无引号)?不确定,就全扫 - 正确写法:先建虚拟列
role_flag TINYINT AS (JSON_CONTAINS(data, '"admin"')) STORED,再查WHERE role_flag = 1 - 注意:
STORED必须显式声明,VIRTUAL列无法建索引,也救不了性能
ORDER BY里的隐式排序失效引发filesort
5.7允许GROUP BY或ORDER BY字段不在SELECT列表里,且可能复用索引隐式排序;8.0默认ONLY_FULL_GROUP_BY + optimizer_switch='derived_merge=on',一旦字段类型不一致(如ORDER BY CAST(id AS CHAR)),优化器无法信任索引顺序,强制Using filesort。
- 检查点:
EXPLAIN结果中Extra列是否含Using filesort或Using temporary - 临时缓解:
SET SESSION optimizer_switch='derived_merge=off'验证是否回归 - 根治办法:统一字段类型,补复合索引覆盖
WHERE + ORDER BY字段,避免运行时转换
真正要盯的不是“有没有隐式转换”,而是“它让优化器放弃了什么”——索引、排序、合并路径。只要EXPLAIN里key为空、rows翻倍、Extra多出磁盘操作,基本就是它干的。别猜,直接看执行计划。











