mysql中的B+树索引与哈希索引的区别与使用场景

来源:这里教程网 时间:2026-02-28 20:52:28 作者:

为什么 MySQL 的 InnoDB 默认用 B+ 树,而不是哈希索引?

因为

InnoDB
存储引擎本身不支持显式创建哈希索引(
HASH
索引),它只支持
B+ 树索引
。你执行
CREATE INDEX ... USING HASH
会报错;只有
MEMORY
引擎才原生支持哈希索引。InnoDB 内部确实有自适应哈希索引(
adaptive hash index
),但它完全由引擎自动管理,不可配置、不可干预,仅对“热点”的
B+ 树
查找路径做缓存加速,不是用户可定义的索引类型。

B+ 树索引能做什么,哈希索引做不到?

B+ 树
支持范围查询、排序、最左前缀匹配、部分列匹配(如联合索引前缀);
HASH
索引只支持等值查询(
=
IN
),且必须提供**全部索引列**才能命中——哪怕你建的是
(a, b)
联合哈希索引,查
WHERE a = 1
也用不上。

B+ 树
:支持
WHERE age > 25
ORDER BY created_at
WHERE user_id = 123 AND status = 'active'
(联合索引前缀匹配)
HASH
:只响应
WHERE id = 1001
这类完整键等值查找;
WHERE id IN (1001, 1002, 1003)
可能走,但效率未必优于 B+ 树
HASH
不存储有序数据,无法用于
MIN()
/
MAX()
优化或索引覆盖排序

哈希索引真比 B+ 树快吗?

单次等值查询理论上是 O(1),但实际受制于哈希冲突、内存分布和引擎实现。在

MEMORY
表中,哈希索引确实比 B+ 树快——前提是数据量不大、无严重哈希碰撞、且查询模式高度集中于等值。但一旦出现哈希桶溢出(overflow chain),性能会急剧下降;而
B+ 树
的磁盘 I/O 和缓存友好性更可控,尤其在大数据量、混合查询(等值 + 范围)场景下优势明显。

MEMORY
引擎的哈希索引要求所有查询列都参与哈希计算,不支持
NULL
值作为索引列
B+ 树
InnoDB
中天然支持聚簇索引(主键即数据存储顺序),减少回表;哈希索引只能是非聚簇的,必然要回查数据行
哈希索引无法利用
key_len
判断实际匹配长度,执行计划中常显示为
ALL
或不准,调试困难

什么时候该考虑哈希索引?

几乎只有一种现实场景:

MEMORY
表 + 极高并发、纯等值查询、数据量稳定且可预估(避免哈希桶分裂)、对延迟极度敏感(微秒级)。例如缓存用户 session ID 到 user_id 的映射表:

CREATE TABLE session_lookup (
  session_id CHAR(32) NOT NULL,
  user_id INT NOT NULL,
  PRIMARY KEY (session_id)
) ENGINE=MEMORY DEFAULT CHARSET=utf8mb4
  AVG_ROW_LENGTH=64 MAX_ROWS=1000000;

此时你可以显式指定哈希索引:

CREATE INDEX idx_session_hash ON session_lookup (session_id) USING HASH;
别在
InnoDB
表上尝试
USING HASH
—— 语法报错:
ERROR 1064 (42000): Syntax error
不要指望哈希索引解决慢查询:如果
EXPLAIN
显示没走索引,换哈希索引大概率也没用,先检查是否满足等值、是否含
NULL
、是否用了函数包裹列(如
WHERE MD5(id) = ?
哈希索引不支持
LIKE 'abc%'
,也不支持索引下推(ICP),这些都得靠 B+ 树

真正需要纠结选型的地方,往往不是“B+ 树 vs 哈希”,而是“要不要加索引”“索引列顺序怎么排”“是否该用覆盖索引”——这些才是日常调优里更常踩坑的位置。

相关推荐