mysql中B+树索引和 Hash 索引有什么区别?
在 MySQL 中,B+树索引和 Hash 索引是两种完全不同的索引结构,它们各有优缺点,适用于不同的查询场景。主要区别如下:
特性
B+树索引
Hash 索引
数据结构
多路平衡搜索树(有序结构)
哈希表(无序结构)
查询类型支持
等值查询
范围查询(>、<、BETWEEN)
排序(ORDER BY)
模糊查询(前缀匹配 LIKE 'abc%')
仅支持等值查询(=、IN())
不支持范围查询
不支持排序
不支持模糊查询
查询效率
等值查询:O(logₙN)(稳定)
范围查询:高效(叶子节点链表)
等值查询:O(1)(理想情况下,极快)
范围查询:不支持
排序支持
天然有序(叶子节点构成链表)
无序(需额外排序操作)
磁盘 I/O 优化
适合磁盘存储(减少 I/O 次数,顺序访问友好)
随机访问多,可能引发更多 I/O
空间利用率
较高(节点填充因子高)
较低(哈希冲突、扩容开销)
索引列重复值
高效处理
哈希冲突影响性能
使用场景
OLTP 主流选择、范围查询、排序、高并发
内存表、精确点查场景、临时表、自适应哈希索引
存储引擎支持
InnoDB(默认)、MyISAM
仅 Memory 引擎显式支持
(InnoDB 有自适应哈希索引)
- 数据结构与基本原理
-
B+树索引: 基于 多路平衡搜索树。数据存储在有序的叶子节点中(形成链表),非叶子节点只存储键值和指向子节点的指针。查询从根节点开始,逐层比较键值,最终定位到叶子节点。
-
Hash 索引: 基于 哈希表。对索引列的值计算一个哈希码(Hash Code),然后将指向数据行的指针存储在哈希表中对应的“桶”(Bucket)里。查询时直接计算键值的哈希码,找到对应的桶(理想情况下时间复杂度 O(1)),再在桶内精确匹配(解决哈希冲突)。
-
支持的查询类型
-
B+树索引:
-
等值查询:
WHERE column = value -
范围查询:
WHERE column > value,WHERE column BETWEEN value1 AND value2等。因为数据在叶子节点是有序存储的。 -
排序:
ORDER BY column。利用叶子节点的链表结构可以高效地按顺序获取数据。 -
前缀匹配模糊查询:
WHERE column LIKE 'prefix%'。可以利用索引的最左前缀特性。 -
Hash 索引:
-
仅支持等值查询:
WHERE column = value或WHERE column IN (value1, value2, ...)。 -
不支持范围查询: 因为哈希表本身是无序的,无法高效定位一个范围。
-
不支持排序: 无序性导致无法利用索引进行排序。
-
不支持模糊查询: 即使是最左前缀
LIKE 'abc%'也不行,因为哈希函数是对整个值计算的。 -
查询效率
-
B+树索引: 等值查询效率是
O(logₙN)(N 是记录数,n 是节点扇出),非常高效且稳定。范围查询效率也很高,因为只需要定位到范围的起始点,然后顺序扫描叶子节点链表即可。 -
Hash 索引: 在没有哈希冲突的理想情况下,等值查询效率是
O(1),理论上比 B+树更快。但是: -
哈希冲突会降低效率(需要遍历冲突链)。
-
范围查询或排序需要全表扫描,效率极低。
-
磁盘 I/O 友好性
-
B+树索引: 设计时充分考虑了磁盘存储特性。树的高度较低(通常 3-4 层就能存储海量数据),每次查询只需几次磁盘 I/O。顺序访问(范围扫描)效率高。
-
Hash 索引: 哈希查找本质上是随机 I/O。桶的位置由哈希函数决定,没有局部性原理。当索引无法完全放入内存时,大量的随机磁盘 I/O 会严重拖慢速度。这是 Hash 索引在磁盘数据库中应用受限的关键原因。
-
空间利用率
-
B+树索引: 空间利用率较高。节点通常填充较满(InnoDB 页默认 16KB)。
-
Hash 索引: 为了减少冲突,哈希表通常需要更大的空间(负载因子小于 1)。桶的数量需要精心管理,扩容(Rehashing)操作开销大。
-
对索引列重复值的处理
-
B+树索引: 可以高效处理重复键值。相同键值的记录会存储在相邻的叶子节点位置(具体实现如 InnoDB 会附加主键保证唯一性)。
-
Hash 索引: 大量重复键值会导致严重的哈希冲突,显著降低查询效率。
MySQL 中的实际应用
-
显式 Hash 索引: 只有
MEMORY存储引擎显式支持创建 Hash 索引。因为它将数据完全存储在内存中,规避了 Hash 索引随机 I/O 的致命缺点。 -
InnoDB 的 Adaptive Hash Index: InnoDB 存储引擎有一个自适应哈希索引特性。它是一个内置的、自动的、透明的优化机制。
-
原理: InnoDB 监控对表上 B+树索引的查询模式。如果发现某些索引值(或其前缀)被非常频繁地以等值查询方式访问,它会在内存中的 Buffer Pool 里为这些热点值自动创建一个 Hash 索引指向 B+树叶子节点上的真实记录。
-
目的: 加速这些特定热点值的查询速度,使其接近 O(1)。
-
用户控制: DBA 可以开启或关闭该特性(
innodb_adaptive_hash_index),或调整其分区数(innodb_adaptive_hash_index_parts)以降低锁争用。 -
关键点:
-
它是对 B+树索引的补充,不是替代。
-
它只针对频繁访问的特定值。
-
它完全由 InnoDB 内部管理,用户无法手动创建或指定哪些列使用 AHI。
-
它利用的是内存 Buffer Pool,不解决磁盘 I/O 问题。
-
NDB Cluster 引擎: 也使用了 Hash 索引作为其主要的索引类型。

发表评论
所有评论