首页 >> 基础教程

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 有自适应哈希索引)


  1. 数据结构与基本原理

    • B+树索引: 基于 多路平衡搜索树。数据存储在有序的叶子节点中(形成链表),非叶子节点只存储键值和指向子节点的指针。查询从根节点开始,逐层比较键值,最终定位到叶子节点。

    • Hash 索引: 基于 哈希表。对索引列的值计算一个哈希码(Hash Code),然后将指向数据行的指针存储在哈希表中对应的“桶”(Bucket)里。查询时直接计算键值的哈希码,找到对应的桶(理想情况下时间复杂度 O(1)),再在桶内精确匹配(解决哈希冲突)。

  2. 支持的查询类型

    1. B+树索引:

      1. 等值查询: WHERE column = value

      2. 范围查询: WHERE column > valueWHERE column BETWEEN value1 AND value2 等。因为数据在叶子节点是有序存储的。

      3. 排序: ORDER BY column。利用叶子节点的链表结构可以高效地按顺序获取数据。

      4. 前缀匹配模糊查询: WHERE column LIKE 'prefix%'。可以利用索引的最左前缀特性。

    2. Hash 索引:

      1. 仅支持等值查询: WHERE column = value 或 WHERE column IN (value1, value2, ...)

      2. 不支持范围查询: 因为哈希表本身是无序的,无法高效定位一个范围。

      3. 不支持排序: 无序性导致无法利用索引进行排序。

      4. 不支持模糊查询: 即使是最左前缀 LIKE 'abc%' 也不行,因为哈希函数是对整个值计算的。

  3. 查询效率

    1. B+树索引: 等值查询效率是 O(logₙN)(N 是记录数,n 是节点扇出),非常高效且稳定。范围查询效率也很高,因为只需要定位到范围的起始点,然后顺序扫描叶子节点链表即可。

    2. Hash 索引: 在没有哈希冲突的理想情况下,等值查询效率是 O(1)理论上比 B+树更快。但是:

      1. 哈希冲突会降低效率(需要遍历冲突链)。

      2. 范围查询或排序需要全表扫描,效率极低。

  4. 磁盘 I/O 友好性

    1. B+树索引: 设计时充分考虑了磁盘存储特性。树的高度较低(通常 3-4 层就能存储海量数据),每次查询只需几次磁盘 I/O。顺序访问(范围扫描)效率高。

    2. Hash 索引: 哈希查找本质上是随机 I/O。桶的位置由哈希函数决定,没有局部性原理。当索引无法完全放入内存时,大量的随机磁盘 I/O 会严重拖慢速度。这是 Hash 索引在磁盘数据库中应用受限的关键原因。

  5. 空间利用率

    1. B+树索引: 空间利用率较高。节点通常填充较满(InnoDB 页默认 16KB)。

    2. Hash 索引: 为了减少冲突,哈希表通常需要更大的空间(负载因子小于 1)。桶的数量需要精心管理,扩容(Rehashing)操作开销大。

  6. 对索引列重复值的处理

    1. B+树索引: 可以高效处理重复键值。相同键值的记录会存储在相邻的叶子节点位置(具体实现如 InnoDB 会附加主键保证唯一性)。

    2. Hash 索引: 大量重复键值会导致严重的哈希冲突,显著降低查询效率。

MySQL 中的实际应用

  1. 显式 Hash 索引: 只有 MEMORY 存储引擎显式支持创建 Hash 索引。因为它将数据完全存储在内存中,规避了 Hash 索引随机 I/O 的致命缺点。

  2. InnoDB 的 Adaptive Hash Index: InnoDB 存储引擎有一个自适应哈希索引特性。它是一个内置的、自动的、透明的优化机制。

    1. 原理: InnoDB 监控对表上 B+树索引的查询模式。如果发现某些索引值(或其前缀)被非常频繁地以等值查询方式访问,它会在内存中的 Buffer Pool 里为这些热点值自动创建一个 Hash 索引指向 B+树叶子节点上的真实记录。

    2. 目的: 加速这些特定热点值的查询速度,使其接近 O(1)。

    3. 用户控制: DBA 可以开启或关闭该特性(innodb_adaptive_hash_index),或调整其分区数(innodb_adaptive_hash_index_parts)以降低锁争用。

    4. 关键点:

      1. 它是对 B+树索引的补充,不是替代。

      2. 它只针对频繁访问的特定值

      3. 它完全由 InnoDB 内部管理,用户无法手动创建或指定哪些列使用 AHI。

      4. 它利用的是内存 Buffer Pool,不解决磁盘 I/O 问题。

  3. NDB Cluster 引擎: 也使用了 Hash 索引作为其主要的索引类型。



最新文章
mysql分页问题2025-08-04
千万数据先insert和先建索引哪个快2025-08-04
MySQL 中大小表关联查询如何优化2025-08-04
sql技巧-每个班年龄排前两名的人2025-08-03
MySQL 导致 cpu 飙升的话,要怎么处理呢?2025-07-29
MySQL 中为千万级大表添加字段2025-07-29
mysql中百万级别以上的数据如何删除2025-07-29
分库分表带来的问题2025-07-29
mysql中常用的分库分表中间件有哪些2025-07-29
mysql不停机扩容2025-07-29
备案号:蜀ICP备2023042032号-1