mysql 8.0优化器对索引使用更严格:order by方向须与索引定义完全一致,联合索引需满足最左前缀且排序字段连续,collation不一致会触发隐式convert导致索引失效。

不是SQL变慢了,是MySQL 8.0的优化器对索引使用条件更较真了——稍有不匹配就弃用索引,转而走Using filesort或全表扫描。
ORDER BY方向不一致直接触发Using filesort
MySQL 5.7对DESC索引字段基本无视,建INDEX(a DESC, b ASC)实际按a ASC, b ASC存;它靠反向扫描“凑合”支持降序查询。MySQL 8.0真正支持降序索引,但要求ORDER BY字段方向必须与索引定义严格一致。
- 索引是
INDEX(user_id ASC, created_at DESC),查询写ORDER BY user_id DESC, created_at ASC→ 8.0直接跳过该索引 - 验证方式:
EXPLAIN中key非空但Extra含Using filesort - 临时绕过:加
/*+ USE_INDEX(@sel_1 tbl_name (idx_name)) */强制走索引
联合索引字段顺序与WHERE+ORDER BY混用失配
8.0更依赖“最左前缀 + 排序连续性”。哪怕WHERE能走索引,只要ORDER BY字段不在WHERE覆盖的最右连续段上,就可能拒绝用索引排序。
- 索引
INDEX(status, category, updated_at),查询WHERE status = ? AND category = ? ORDER BY updated_at DESC→ 可免排序 - 同索引下写
ORDER BY status, updated_at→ 因status和updated_at不连续(中间缺category),索引排序失效 - 修复关键:把所有
ORDER BY字段尽量放在索引右侧连续位置,避免穿插非排序字段
COLLATION不一致导致隐式CONVERT()阻断索引
这是升级后最隐蔽的性能断崖点:连接默认collation_connection是utf8mb4_0900_ai_ci,而表字段是utf8mb4_general_ci,MySQL 8.0会在比较前自动加CONVERT(col USING utf8mb4_0900_ai_ci)——只要出现这个函数,B+树索引立即失效。
- 常见于
JOIN:ON t1.name = t2.name,两张表name字段COLLATION不同 → 触发隐式转换 - 现象:
EXPLAIN中type降为ALL或key为NULL,但字段明明有索引 - 快速确认:
SELECT @@collation_connection,再查INFORMATION_SCHEMA.COLUMNS比对字段实际COLLATION
真正难调的不是单条SQL,而是那些在5.7里“碰巧跑得动”的查询——它们往往依赖旧版优化器的宽容行为,升级后暴露的是索引设计本身不够严谨。别急着改SQL,先看EXPLAIN FORMAT=TREE里每一步的cost_info和used_columns,那里藏着8.0真正想怎么执行的线索。











