先看现象,再逐个追问“为什么”。下面 SQL 是独立的教学例子;每条是否选择索引仍与真实建表、数据分布和 MySQL 版本有关。
| 原因 | 典型 SQL / 前提 | 真正要理解的结论 |
|---|---|---|
| 1. 联合索引缺少最左列 | WHERE b=1;索引 (a,b,c) | 无法按 b 直接找到一个全局连续区间;某些条件允许 Skip Scan。 |
| 2. 索引列使用函数 | YEAR(create_time)=2026 | 普通索引按原始日期排序,而非按年份表达式排序。 |
| 3. 索引列参与计算 | age+1=30 | 原始索引不能直接按 age+1 的结果定位。 |
| 4. 隐式类型转换 | phone=13800138000;列是 VARCHAR | 字符串列与数字比较可能要求对列值转换。 |
| 5. LIKE 前面带通配符 | name LIKE '%张三' | 不知道字符串开头,就不能直接找到相邻的前缀区间。 |
| 6. OR 两侧索引条件不佳 | WHERE a=1 OR b=2 | 需要兼顾两侧的候选记录;可能走 Index Merge,也可能全表扫描。 |
| 7. 范围列后继续过滤 | a=1 AND b>10 AND c=3;索引 (a,b,c) | c 通常不能继续缩小连续索引扫描范围,但仍可能在索引层过滤。 |
| 8. 否定条件 | status != 1 | 可能命中大量行;不等于操作符绝非“必定不用索引”。 |
| 9. 区分度低 | gender=1;符合条件占 60% | 大量回表可能比直接读表更贵。 |
| 10. 数据少或返回太多 | SELECT * FROM orders | 没有限制条件时,全表扫描往往就是合理方案。 |
OR、!=、范围条件、缺少最左列都不是必然导致“完全不使用索引”。面试官更在意为什么、如何验证,以及具体是哪一部分无法参与定位。