key为空但possible_keys有值,通常不是优化器选错而是索引根本未创建;应先用show index确认是否存在,再查备份文件或show create table验证建表语句是否含索引定义,避免依赖navicat图形界面生成错误sql。
key为空但possible_keys有值,先别急着调优
这通常不是优化器“选错了”,而是你根本没建那个索引。navicat还原数据库时,如果备份是.nb3格式或还原向导没勾选「索引」,show index from table_name会直接返回空——但执行计划里possible_keys却可能显示一堆名字,这是mysql从字典缓存或旧元数据里“猜”的,不可信。
实操建议:
- 运行
SHOW CREATE TABLE table_name,看建表语句末尾有没有KEY idx_name (col1, col2)这类定义 - 打开原始
.sql备份文件,全文搜索CREATE INDEX或UNIQUE KEY,确认是否真包含该索引 - 别依赖Navicat「设计表 → 索引」界面点选添加——它生成的SQL常漏
USING BTREE,大小写也容易错
type = ALL 且 rows 很小,但 key 是 NULL,基本坐实没建
比如EXPLAIN SELECT * FROM orders WHERE status = 'shipped'返回type: ALL、rows: 42、key: NULL,且possible_keys也为空,说明优化器连“可选索引”都看不到。这不是统计信息问题,是结构缺失。
常见诱因:
- WHERE字段类型和条件值类型不一致,如
status是VARCHAR却写了WHERE status = 1(此时possible_keys通常不为空,可用来区分) - 联合索引最左前缀不匹配:建了
(user_id, status),但查询只用WHERE status = 'active',索引完全不可用,possible_keys也会为空 - Navicat同步时勾选了
Ignore AUTO_INCREMENT value,导致主键索引范围判断失准,间接让优化器放弃使用
Navicat执行计划默认不显示关键字段,得手动展开
默认表格只显示id、select_type、table、type、possible_keys、key等基础列,但key_len和ref才是判断是否真走索引的核心依据。
实操建议:
- 右键执行计划结果表格 → 选「显示所有列」,重点看
key_len是否为0、ref是否为NULL——两者同时成立,基本确认没走任何索引 - 在SQL前加
EXPLAIN FORMAT=JSON(MySQL 5.6+),Navicat v15.5+能解析出used_indexes字段,明确告诉你用了哪些索引 - 别信顶部状态栏显示的“耗时”,那是网络+解析+传输时间,不是数据库真实执行时间
别把ANALYZE TABLE当万能药,先分清“没建”还是“没用”
ANALYZE TABLE只刷新统计信息,对真缺失的索引毫无作用。而OPTIMIZE TABLE实际执行的是重建表,耗时长、锁表久,还掩盖了根本问题。
判断逻辑很直接:
-
SHOW INDEX FROM table_name输出为空 → 索引缺失 → 手写CREATE INDEX idx_status ON orders(status) USING BTREE; -
SHOW INDEX有索引,但EXPLAIN中key为空 → 统计过期 → 执行ANALYZE TABLE orders; - 大表加索引前,务必确认权限:
SHOW GRANTS FOR CURRENT_USER;,缺INDEX权限得找DBA补
联合索引的列序一旦写反,比如查WHERE category = ? AND created_at > ?却建了(created_at, category),等于白建——这种错误在Navicat图形界面里特别容易发生,手写SQL反而更可控。











