执行计划中key为空且type为all,说明该列未走索引;若possible_keys有值而key为空,则索引存在但被优化器跳过,常见于最左前缀不匹配、隐式类型转换或数据量过小。
怎么看执行计划里哪列没走索引
直接在 navicat 查询编辑器中写好慢 sql,右键选中 → 点击“解释”(或按 ctrl+e),看返回的执行计划表格。重点盯三列:type、key、rows。type 是 all 就是全表扫描;key 为空说明压根没用上索引;rows 值远大于实际结果行数(比如查 10 条却扫了 50 万行),说明索引没生效或选错了。
WHERE 条件字段顺序决定复合索引怎么建
Navicat 的“设计表 → 索引”页能直观看到现有索引字段顺序。但关键是要对齐查询条件:如果经常写 WHERE status = ? AND category = ? ORDER BY created_at DESC,那索引就得按 (status, category, created_at) 的顺序建——不能反过来,也不能漏掉 status。MySQL 遵守最左前缀原则,跳过第一个字段(比如只查 category),这个复合索引就完全失效。
- 等值条件字段(
=、IN)放前面,范围条件(>、BETWEEN)放中间,排序/分组字段(ORDER BY、GROUP BY)放最后 - 避免在 WHERE 里对字段用函数:
WHERE DATE(create_time) = '2024-01-01'会让索引失效;改成WHERE create_time >= '2024-01-01' AND create_time - Navicat 可视化建索引时,在“索引”选项卡点“+”,填名称、选字段、类型选
Normal(InnoDB 默认用BTREE)即可
什么时候该用 FORCE INDEX 而不是改 SQL
执行计划显示 possible_keys 有值但 key 为空,说明优化器“觉得”不值得用索引(比如它误判数据分布、或统计信息过期)。这时可临时加 FORCE INDEX(index_name) 强制走索引验证效果,例如:SELECT * FROM orders FORCE INDEX(idx_user_id) WHERE user_id = 123。但这是兜底手段,不是长期方案——得接着更新统计信息(ANALYZE TABLE orders)或检查索引是否真覆盖了查询路径。
建完索引必须验证是否真的被用了
很多人建完索引就以为万事大吉,结果执行计划里 key 还是空。常见原因包括:字段类型隐式转换(比如 user_id 是 BIGINT,但 WHERE 里传了字符串 '123')、索引字段上有 OR 或 !=、或者查询里用了 SELECT * 导致回表代价高,优化器干脆放弃索引。最稳妥的方式是:建索引 → EXPLAIN 看执行计划 → 实际跑一遍 SQL 记录耗时 → 对比建索引前后 rows 和执行时间变化。别只看 Navicat 底部状态栏的“查询成功”,要看它到底扫了多少行。











