SQL数据库索引底层原理_BTree与Hash索引对比

13次阅读

mysql默认使用B+Tree索引,因其将数据全存于叶子节点、非叶节点仅存键和指针,树更矮、IO更少,且天然支持范围查询、最左前缀匹配和覆盖索引。

SQL数据库索引底层原理_BTree与Hash索引对比

MySQL 默认用 B+Tree,不是纯 B-Tree,也不是 Hash。B+Tree 是 B-Tree 的改进版,专为磁盘 I/O 和范围查询优化;Hash 索引只适合等值查询,且不支持排序、范围、前缀匹配。

B+Tree 索引为什么是主流

它把所有数据都存放在叶子节点,非叶子节点只存索引键和子节点指针,这样单个节点能容纳更多键,树更矮、IO 更少。比如 1000 万数据,B+Tree 高度通常只有 3~4 层,查一次最多 4 次磁盘读取。

  • 支持等值查询:通过二分查找快速定位目标键
  • 天然支持范围查询:叶子节点用双向链表连接,扫一段连续地址即可
  • 支持最左前缀匹配:联合索引 (a,b,c) 可用于 where a=1、where a=1 and b>2、where a=1 and b=2 and c in (1,2)
  • 减少回表开销:覆盖索引时,查询字段全在索引中,无需再查主键聚簇索引

Hash 索引的适用场景和硬伤

Hash 索引底层是一张哈希表,key 是索引列计算出的哈希值,value 是对应行的地址。它的查找是 O(1),但仅限于 = 或 这类完全匹配。

  • 不支持范围查询:where age > 25 无法用 Hash 索引
  • 不支持模糊匹配:like ‘zhang%’、left(name,2)=’zh’ 都失效
  • 哈希冲突会导致链表或开放寻址,性能不稳定
  • InnoDB 不支持显式创建 Hash 索引(MEMORY 引擎才原生支持)
  • 无法利用索引做排序:order by、group by 都要额外排序

B-Tree 和 B+Tree 的关键区别

B-Tree 每个节点既存键也存数据(或数据指针),而 B+Tree 把数据全部下推到叶子层,非叶节点纯做导航。这带来三个实际好处:

  • 同样大小的页,B+Tree 能装更多键 → 树更矮 → 查询更快
  • 叶子节点连成有序链表 → 范围扫描不用反复跳转,顺序 IO 效率高
  • 非叶节点不存数据 → 更新时缓存更集中,写放大更小

什么时候该考虑 Hash?

极少数情况可手动模拟:比如用 CRC32 或 MD5 对长字符串建前缀索引 + 辅助字段,再加唯一约束防冲突。但日常开发中,InnoDB 表几乎不需要主动选 Hash —— 它的优化器甚至不会对 Hash 索引生成执行计划。

真正用 Hash 的典型场景是内存表(MEMORY 引擎)、redis 缓存键设计、或数据库内部的自适应哈希索引(AHI),那是 InnoDB 在运行时自动为热点 B+Tree 页面建立的加速缓存,用户不可控也不需干预。

text=ZqhQzanResources