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

8次阅读

innodb默认用b+树而非哈希索引,因其仅支持b+树(create index … using hash报错),且b+树支持范围查询、排序、最左前缀匹配,而哈希索引仅支持完整键等值查询,不支持范围、排序、NULL值及索引下推。

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

为什么 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 > 25ORDER BY created_atWHERE 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 哈希”,而是“要不要加索引”“索引列顺序怎么排”“是否该用覆盖索引”——这些才是日常调优里更常踩坑的位置。

text=ZqhQzanResources