最关键看 rows 和 filtered 的乘积,它近似代表 MySQL 实际扫描的行数;其次关注 Extra 是否出现 Using filesort 或 Using temporary,key_len 是否符合预期,以及隐式类型转换导致 key 为空。

EXPLAIN 输出里哪些字段最关键
看 EXPLAIN 结果,别只盯着 type 和 key,真正决定性能的是 rows 和 filtered 的乘积——它近似代表 MySQL 实际扫描的行数。比如 rows=10000 且 filtered=10.00(即 10%),意味着大概要检查 1000 行;但如果 filtered 是 0.1,那就得筛 10 行——差别巨大。
常见误判:看到 type=ref 就以为没问题,但若 rows 是百万级,说明索引没过滤掉多少数据,可能需要更选择性的索引或调整查询条件顺序。
-
key为空?说明没走索引,先查possible_keys是否有候选,再确认 WHERE 条件是否符合最左前缀原则 -
Extra出现Using filesort或Using temporary?大概率是排序/分组字段没被索引覆盖,需加联合索引 -
key_len比预期小?比如定义了INDEX(a,b,c),但key_len只显示 a 的长度,说明 b/c 没参与索引查找——通常因为 WHERE 中跳过了 b
联合索引怎么建才不浪费
联合索引不是字段堆砌,而是按「过滤性 + 查询频率 + 排序需求」排优先级。高区分度字段(如 user_id)放前面,低区分度(如 status)放后面;等值查询字段优先于范围查询字段(WHERE a=1 AND b>100 → 索引应为 (a,b),不能是 (b,a))。
容易踩的坑:ORDER BY 字段必须紧接在 WHERE 等值字段之后,才能复用索引避免 Using filesort。例如 WHERE category=2 AND is_valid=1 ORDER BY created_at DESC,索引应为 (category, is_valid, created_at),而不是 (category, created_at, is_valid)。
- 字符串字段加索引要控制长度:
VARCHAR(255)不必全字段索引,INDEX(title(191))足够应对多数场景,还能节省 B+ 树层级 - 避免冗余索引:
INDEX(a)和INDEX(a,b)同时存在时,前者基本无效,删掉 - 日期范围慎用:对
created_at > '2023-01-01'单独建索引效果差,应结合高选择性字段组成联合索引
为什么 force index 有时反而更慢
FORCE INDEX 是告诉优化器“必须用这个索引”,但它不解决底层数据分布问题。如果该索引的 rows 预估远高于实际最优路径(比如统计信息过期),强制使用只会让执行计划更糟。
典型场景:表刚导入大量数据,但没 ANALYZE TABLE,优化器仍按旧统计估算,此时 FORCE INDEX 可能锁死在低效路径上;或者索引本身覆盖不全,导致回表次数爆炸(Extra 出现大量 Using where + 高 rows)。
- 先跑
ANALYZE TABLE table_name更新统计信息,再看EXPLAIN是否自动选对索引 - 用
SELECT * FROM table_name WHERE ...对比SELECT id FROM table_name WHERE ...的EXPLAIN,判断是否因回表成本过高导致优化器弃用索引 -
FORCE INDEX仅用于临时验证,上线前务必还原并靠索引设计和统计信息解决根本问题
慢查询里隐式类型转换怎么揪出来
当 WHERE 条件字段是 VARCHAR,但传入数字(如 WHERE phone = 13812345678),MySQL 会把整列转成数字比较,导致索引失效——EXPLAIN 中 key 为空,type 变成 ALL。
这种问题在 ORM 自动生成 SQL 时特别隐蔽,比如 MyBatis 把 Java Long 直接拼进字符串条件,或前端传参没加引号。检查方法很简单:把慢查询日志里的 SQL 拿到 MySQL 客户端执行,再 EXPLAIN,重点看 type 和 key 是否异常。
- 统一用字符串传参:
WHERE phone = '13812345678' - 建表时尽量让字段类型和业务输入一致,避免
INT存手机号(后期想加前缀就崩溃) - 用
SHOW WARNINGS查看隐式转换警告,MySQL 8.0+ 会在警告中明确提示 “Cast to type …”
实际调优中,90% 的索引问题出在联合索引字段顺序、字符串字段未截取长度、以及隐式类型转换这三处。只要每次写完查询都扫一眼 EXPLAIN 的 rows 和 Extra,就能避开大部分线上性能雷区。










