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

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










