mysql如何查看SQL是否走索引_mysql查询优化技巧

9次阅读

判断索引是否生效应优先查看EXPLaiN的key和type字段:key非NULL且type不为ALL或index即走索引;type=ref/eq_ref表示高效索引访问,range为范围扫描,ALL为全表扫描需优化;key为NULL说明索引未被选用。

mysql如何查看SQL是否走索引_mysql查询优化技巧

直接看 EXPLAINkeytype 字段

这是最快速、最可靠的判断方式。只要 key 列非 NULL,且 type 不是 ALLindex(全索引扫描),基本就走索引了。

  • type = refeq_ref:走了二级索引或主键/唯一索引,效果好
  • type = range:走了索引范围扫描(如 WHERE age BETWEEN 25 AND 35
  • type = ALL:没走索引,全表扫描——性能杀手,优先优化
  • key 为空或显示 NULL:即使有索引,也没被选中

示例:

EXPLAIN SELECT * FROM users WHERE email = 'a@b.com';

如果返回中 key: idx_emailtype: ref,说明成功命中索引;若 key: NULL + type: ALL,就得继续排查原因。

为什么有索引却没走?常见踩坑点

建了索引 ≠ 查询自动用索引。mysql 优化器会基于成本估算决定是否使用,而“成本低”不等于“有索引就一定用”。

  • 隐式类型转换WHERE user_id = '123'user_idint)→ 触发全表扫描,因为字符串转整数会让索引失效
  • 对索引列用函数:WHERE YEAR(create_time) = 2024 → 索引无法下推,改写为 create_time BETWEEN '2024-01-01' AND '2024-12-31'
  • 前导模糊匹配:WHERE name LIKE '%abc' → B+树无法从左匹配,索引失效;LIKE 'abc%' 可用
  • 索引选择性太低:比如给只有两个值的 gender 列建索引,优化器大概率放弃它
  • 数据量极小(如几百行):优化器可能认为全表扫描比回表+索引查找更快

辅助验证:查索引是否存在 & 是否被统计

有时你以为有索引,其实根本没建,或者建错列了。用这两条命令交叉验证:

  • 查索引定义:
    SHOW INDEX FROM users;

    确认 Column_nameKey_name 是否符合预期(比如你查 email,但索引建在 user_email 上)

  • 查索引统计信息(反映优化器“认知”):
    SELECT * FROM mysql.innodb_index_stats WHERE database_name = 'your_db' AND table_name = 'users';

    n_diff_pfx01(基数)异常低,说明统计过期,可手动更新:ANALYZE TABLE users;

进阶定位:用 optimizer_trace 看优化器真实决策

EXPLAIN 显示没走索引,但你觉得“它应该走”,就可以打开优化器跟踪,看它到底怎么想的:

SET optimizer_trace="enabled=on"; SELECT * FROM users WHERE status = 1 AND created_at > '2025-01-01'; SELECT * FROM information_schema.optimizer_traceG SET optimizer_trace="enabled=off";

重点关注 analyzing_range_alternativesusing_index_for_order_by 段落,里面会明确写出:“该索引成本为 123.45,全表扫描成本为 89.12,故选择后者”。这才是真正的原因,不是玄学。

注意:optimizer_trace 是会话级的,别忘了关;而且它只对当前会话生效,不能查别人跑的 SQL。

text=ZqhQzanResources