案例 MySQL 8.4 索引新坑:Skip Scan 别乱用,OPTIMIZE TABLE 可以省了

2026-08-29 21:09:12

MySQL 8.4 索引新坑:Skip Scan 别乱用,OPTIMIZE TABLE 可以省了

MySQL 8.4 普及之后,索引机制确实带来了一些新优化。但实际排查慢 SQL 时你会发现:索引失效的核心坑点一个没少,反而多了两个版本专属的避坑点。

这篇文章就当一份工程师笔记,把这几个坑记清楚。

坑 1:索引不是越多越好

这个坑从 5.x 时代就有,8.4 也没变。

很多人认为“查询慢就加索引”,于是每个字段都塞进索引。但索引会直接拉低 INSERT / UPDATE / DELETE 的效率,因为每次写入都要同步维护索引 B+ 树。

生产环境中,单表索引建议不超过 5 个。超过这个数,写入性能基本可以肉眼感知到下降。

坑 2:别依赖 8.4 的 Skip Scan

MySQL 8.4 开始支持跳过扫描(Skip Scan),允许查询跳过联合索引的中间列直接走索引。听起来很美好,但限制非常严格:

  • 仅限等值查询
  • 字段选择性必须高

这两条在生产环境很难同时满足。一旦选择性不够,优化器根本不会走 Skip Scan,索引照样失效。

所以,设计联合索引时仍然以最左前缀匹配为准。Skip Scan 只能当成一个“偶尔能捞一手的补充”来看待,不能作为设计依据。

坑 8:8.4 的索引碎片自动清理,别手动 OPTIMIZE TABLE

MySQL 8.4 及以上版本对索引碎片有了自动清理机制,这意味着:不再需要手动执行 OPTIMIZE TABLE。

很多人还在沿用旧习惯,定期去跑 OPTIMIZE TABLE 维护表。在 8.4 上这反而是一个坑:OPTIMIZE TABLE 会锁表,生产环境一旦执行,直接阻塞写入。

版本差异要清楚:

  • MySQL 8.4 及以上:碎片自动清理,无需手动 OPTIMIZE
  • MySQL 8.0 及以下:依然需要根据实际情况手动维护

升级到 8.4 之后,请把定时任务里的 OPTIMIZE TABLE 删掉。

慢 SQL 优化的核心

90% 的慢 SQL 是索引用错,不是没索引。

所以优化的重点不是盲目加索引,而是用 EXPLAIN 找到索引失效的根因,再做针对性调整。

EXPLAIN 输出中,重点看四个点:

  • type:ALL 表示全表扫描,最慢;至少要达到 range 或 ref
  • key:实际命中的索引。如果为 NULL,说明索引没被使用
  • rows:预估扫描行数,数值越大越危险
  • Extra:Using filesort 表示排序没走索引;Using temporary 会创建临时表,性能极差;Using index 是最优的覆盖索引

只要发现 type=ALL、key=NULL、Extra 里出现 filesort 或 temporary,基本可以断定这条 SQL 的索引设计有问题。

取舍总结

项目结论
索引数量单表不超过 5 个,宁缺毋滥
Skip Scan8.4 支持,但仅限等值查询且字段选择性高,生产环境切勿依赖
索引碎片8.4 及以上自动清理,手动 OPTIMIZE TABLE 反而造成锁表
慢 SQL 判断依赖 EXPLAIN,而不是靠猜

MySQL 8.4 的优化确实有,但版本升级不改变一个事实:索引设计要回到最左前缀匹配这条基本线上,配合 EXPLAIN 验证,而不是相信某个新特性可以偷懒。

复制全文 生成海报 MySQL 索引 版本差异

推荐文章

程序员茄子在线接单