索引失效本质是优化器认为走索引代价高于全表扫描,EXPLAIN中type=ALL或key=NULL即为明确信号;需通过EXPLAIN观察type、key、rows及Extra字段综合判断。

MySQL 出现索引失效,本质不是“索引坏了”,而是优化器在生成执行计划时,判断走索引的代价高于全表扫描,于是主动放弃索引——EXPLAIN 中 type=ALL 或 key=NULL 就是明确信号。
怎么看是不是真失效了?别猜,用 EXPLAIN
加 EXPLAIN 是唯一可靠方式,不执行 SQL 就能看优化器怎么想:
-
type字段是核心指标:从const、ref到range都算合理使用索引;一旦变成index(全索引扫描)或ALL(全表扫描),基本就是失效了 -
key字段为NULL,说明没选任何索引;即使非空,也要结合rows看预估扫描行数是否远超实际命中数 -
Extra里出现Using filesort或Using temporary不直接等于索引失效,但常伴随排序/分组未命中索引,需警惕
WHERE 里一动函数,索引就“隐身”
索引 B+ 树里存的是原始值,不是计算结果。只要对索引列做任何运算,优化器就无法用树结构快速定位。
- ❌
WHERE YEAR(create_time) = 2024→YEAR()让create_time索引失效 - ❌
WHERE price * 1.1 > 100→ 表达式计算强制全表扫描 - ✅ 改成范围查询:
WHERE create_time >= '2024-01-01' AND create_time - ✅ MySQL 5.7+ 可建生成列:
ADD COLUMN create_year INT AS (YEAR(create_time)) STORED,再给它加索引
联合索引没按顺序用,左边一空,右边全废
联合索引 KEY idx_name_age_city(name, age, city) 的结构是先按 name 排,相同 name 再按 age 排,最后才按 city 排。跳过前面,后面就失去有序性基础。
解析 MySQL 8.0 的 DDL 脚本,并将表结构导出为 Excel 格式。适用于用户需将 MySQL 的 `CREATE TABLE` 语句转换为结构化的 Excel 文件场景,导出内容包含字段名、数据类型、长度及精度等信息。支持多张表的批量处理,每张表对应 Excel 中的一个独立工作表。适用于数据库文档编写、数据字典生成及模式分析等任务。
- ❌
WHERE age = 25→ 没name条件,无法定位起始位置,只能扫全表 - ❌
WHERE name = '张三' AND city = '北京'→ 缺age,city无法利用索引(范围查询后右边列失效) - ✅
WHERE name = '张三' AND age BETWEEN 20 AND 30→ 最左匹配 + 范围,age有效,city无效但合理 - ✅ 真要查
city,单独建索引或调整联合索引顺序(如(city, name))
隐式类型转换:看着像对,其实悄悄绕开索引
字段是 VARCHAR,你传数字;字段是 INT,你传字符串——MySQL 会自动转换,等价于在字段上套了个函数,索引立刻失效。
- ❌
SELECT * FROM users WHERE id = '123'→id是INT,字符串触发隐式转换 - ❌
SELECT * FROM products WHERE sku = 987654321→sku是VARCHAR,数字触发转换 - ✅ 始终保持类型一致:数值字段用数字,字符串字段用带引号的字符串
- ✅ 查看
SHOW CREATE TABLE确认字段类型,开发时统一参数类型,别依赖数据库“帮忙”
真正难处理的不是这些典型场景,而是当 rows 预估严重偏差、或统计信息过期时,优化器会“误判”成本——这时候 ANALYZE TABLE 比改 SQL 更管用。另外,OR 条件只要一边没索引,整个条件大概率退化,这点容易被忽略。










