MySQL默认用B+树因范围查询高效、IO更少、稳定性好,哈希不支持范围查询;索引失效主因破坏有序性,如函数操作、隐式转换;执行计划中type、key、rows、Extra字段反映索引使用质量。

MySQL 索引是面试中必问的核心知识点,真正拉开差距的不是“知道有B+树”,而是能否说清 为什么用B+树、什么时候索引失效、如何判断执行计划是否走索引。下面直击高频问题本质,不堆概念,只讲实战逻辑。
为什么 MySQL 默认用 B+ 树,而不是哈希、B树或红黑树?
B+ 树在数据库场景下是综合最优解:
-
范围查询高效:叶子节点用双向链表串联,查
WHERE id BETWEEN 100 AND 200只需定位起点后顺序遍历,B树和红黑树需多次回溯父节点 - IO 更少:非叶子节点只存键值+指针,不存数据,单页能装更多分支,树高更低(通常 3~4 层),一次查询最多 3~4 次磁盘 IO
- 稳定性好:B+ 树严格平衡,任何 key 查找路径长度一致;红黑树插入/删除可能退化,B树叶子层深度不一致
-
哈希索引局限大:仅支持等值查询(
=、IN),不支持范围、排序、模糊前缀(LIKE 'abc%');且无法利用联合索引的最左前缀
哪些写法会导致索引失效?关键看“能否用上索引的有序结构”
索引失效的本质是优化器无法利用 B+ 树的有序性跳过扫描——不是“没建索引”,而是“建了也白建”:
-
对索引列做函数操作:
WHERE YEAR(create_time) = 2023→ 改成WHERE create_time >= '2023-01-01' AND create_time -
隐式类型转换:索引字段是
VARCHAR,却写WHERE user_id = 123(数字)→ MySQL 自动转成字符串比较,但可能放弃索引(取决于字符集和 collation) -
LIKE 通配符开头:
WHERE name LIKE '%张'无法用索引;WHERE name LIKE '张%'可以(最左前缀匹配) -
OR 连接非全索引字段:
WHERE a = 1 OR b = 2,若只有(a)索引,b部分会全表扫描;应建联合索引(a,b)或确保两边都有索引 -
IS NULL / IS NOT NULL 在某些版本不走索引:尤其对允许 NULL 的字段,建议用默认值替代(如
status TINYINT DEFAULT 0),查WHERE status = 0
怎么确认 SQL 真的走了索引?别只看“key”字段
EXPLAIN 是基础,但关键看这几列:
-
type:从好到差是
const > eq_ref > ref > range > index > ALL。ALL是全表扫描,index是全索引扫描(比 ALL 快但仍是扫完所有叶子节点) -
key:显示实际使用的索引名。为
NULL表示没走索引(注意:可能走了主键索引但显示 PRIMARY,不算 NULL) -
rows:预估扫描行数。如果远大于结果集数量(比如
SELECT COUNT(*)返回 1000,rows 却是 100000),说明索引选择不佳或统计信息不准(可ANALYZE TABLE更新) -
Extra:出现
Using filesort或Using temporary是危险信号,意味着排序/分组没走索引,触发了额外的内存或磁盘操作
联合索引设计:为什么必须遵守最左前缀原则?
B+ 树索引按联合索引定义顺序排序存储,就像字典先按姓排、再按名排:
- 索引
(a, b, c)能加速:WHERE a = 1、WHERE a = 1 AND b = 2、WHERE a = 1 AND b = 2 AND c = 3、WHERE a = 1 AND b IN (2,3) - 但不能加速:
WHERE b = 2(跳过 a)、WHERE a > 1 AND b = 2(a 范围查询后,b 无序)、WHERE b = 2 AND c = 3(完全跳过 a) - 口诀:等值字段放左边,范围查询放最右,区分度高的列优先。例如用户表,
(status, create_time)比(create_time, status)更实用——因为常查status = 'active'再按时间排序










