索引是数据库查询性能的分水岭,b+树因其支持范围查询、高io效率和稳定性成为mysql默认结构;建索引需关注选择性、短字段优先及组合索引最左前缀原则。

索引就是数据库的“目录”,不是可有可无的加速器,而是查询能否跑得动的分水岭
没有索引时,select * FROM users WHERE email = 'a@b.com' 可能要扫描几百万行;加了索引后,MySQL 直接跳到目标位置,只查 1–3 层 B+ 树节点。这不是“快一点”,而是从 O(n) 降到 O(log n)——1000 万行数据,全表扫描平均扫 500 万行,B+ 树最多查 4 次磁盘(假设扇区大小和填充率典型值)。关键在于:索引不是为“偶尔慢一下”准备的,是为“每次都要快”设计的基础设施。
为什么 B+ 树是 MySQL 默认索引结构,而不是哈希或普通二叉树
哈希索引(如 MEMORY 引擎支持)只能做等值查询(=),不支持 ORDER BY、BETWEEN、LIKE 'abc%';普通二叉树在数据写入不均衡时会退化成链表,查询变 O(n)。而 B+ 树:
- 所有数据都在叶子节点,且叶子节点用双向链表连起来 → 支持范围扫描和排序
- 非叶子节点只存键值不存行数据 → 单页能放更多分支,树更矮,IO 更少
- 每个节点填充分率通常 ≥50% → 插入/删除时分裂合并可控,稳定性强
所以 InnoDB 所有索引(包括主键)底层都是 B+ 树,连 PRIMARY KEY 本身都决定了数据物理存储顺序。
哪些字段适合建索引?别只看“WHERE 里用了”,要看选择性和过滤效率
判断一个字段值是否值得索引,核心公式是:选择性 = count(DISTINCT column) / COUNT(*)。比如:
-
email字段选择性接近 1.0(每人邮箱基本唯一)→ 强烈推荐索引 -
status enum('active','inactive','pending')选择性最多 0.33 → 即使出现在 WHERE 中,MySQL 也大概率放弃走索引,改用全表扫描 -
created_at时间戳选择性高,但若常查WHERE created_at > '2025-01-01',需确认该范围是否真的过滤掉大量数据;如果近 90% 数据都满足条件,索引收益极低
另外,短索引更优:VARCHAR(50) 比 VARCHAR(500) 建索引更快、更省空间、缓存命中率更高——哪怕你只存 10 个字符,定义过长也会让索引页容纳更少键值,拖慢遍历速度。
组合索引怎么写才真正生效?最左前缀不是玄学,是 B+ 树搜索路径的硬约束
建了 INDEX idx_user_role_status (role, status, created_at),以下查询能用上索引:
WHERE role = 'admin'WHERE role = 'admin' AND status = 'active'WHERE role = 'admin' AND status = 'active' AND created_at > '2025-01-01'
但这些不行:
-
WHERE status = 'active'(跳过最左列role,无法定位子树) -
WHERE role = 'admin' AND created_at > '2025-01-01'(中间缺失status,created_at无法利用有序性)
真正容易被忽略的是:如果经常按 status 单独查,又需要 role + status 联合查,不要盲目建两个单列索引——优先建 (status, role) 组合索引,再看执行计划是否覆盖全部场景;否则多索引会吃磁盘、拖慢写入,还可能让优化器选错索引。
索引不是建得越多越好,也不是建了就自动生效;它依赖你对查询模式、数据分布和 B+ 树工作方式的真实理解。一个没被 EXPLAIN 验证过的索引,和没建一样。