自适应哈希索引(ahi)仅对buffer pool中被频繁访问的b+树叶子页自动构建哈希项,加速等值查询最后一步定位至o(1),但需满足完全匹配、页未驱逐、无函数/隐式转换、联合索引全左前缀等条件;其生效须通过show engine innodb status中hash searches/s与non-hash searches/s比值>0.5验证,且受锁竞争、ddl及buffer pool大小显著影响。

自适应哈希索引(AHI)不会被你的SQL语句“调用”,它只在满足特定访问模式的热点页上悄悄生效;想靠它提速,关键不是写对SQL,而是让InnoDB“愿意建”且“能持续用”。
哪些等值查询可能触发AHI?
AHI只对B+树叶子页上的完全匹配等值查询起作用,且要求访问路径稳定、高频、无干扰:
-
WHERE id = ?(主键或唯一索引全匹配)——最典型场景,但前提是该页在buffer pool中驻留足够久且被连续查够次数 -
WHERE (a,b) = (?,?)(联合索引全左前缀匹配,且查询值组合始终落在同一叶子页)——注意:跨页同键不共享AHI条目 -
WHERE user_id = 'abc' COLLATE utf8mb4_bin(显式指定确定collation,避免隐式转换破坏哈希键提取) - 不触发的常见情况:
WHERE ABS(id) = 100(含函数)、WHERE a = 1(联合索引(a,b)只用左前缀,B+树扫描路径不稳定)、WHERE id IN (1,2,3)(IN列表过长可能跳过AHI路径)
怎么确认当前查询真正在用AHI?
EXPLAIN里看不到AHI,rows_examined也不反映它——它不计入扫描行数。唯一可靠方式是实时观测InnoDB内部指标:
- 执行
SHOW ENGINE INNODB STATUS\G,滚动到INSERT BUFFER AND ADAPTIVE HASH INDEX小节,关注hash searches/s和non-hash searches/s比值;比值 > 0.5 才说明AHI活跃参与 - 更细粒度验证:跑10轮相同
SELECT * FROM t WHERE pk = 123,再查一次status——若hash searches/s明显跳升,说明该键已上AHI - 查performance_schema:
SELECT * FROM performance_schema.innodb_metrics WHERE name IN ('innodb_hash_searches', 'innodb_hash_searches_btree'),差值增大即AHI命中增加
为什么开了AHI却没提速,甚至变慢?
AHI不是万能加速器,它的副作用在高并发点查下容易暴露:
- 全局
hash_lock争用:默认innodb_adaptive_hash_index_parts = 8,8个分区共用一把锁;QPS上万时可能成为瓶颈 - Buffer Pool压力反增:大批量
INSERT/UPDATE会频繁淘汰/重建AHI条目,加剧页换入换出 - DDL期间失效:
ALTER TABLE ... ALGORITHM=COPY会清空全部AHI;ALGORITHM=INPLACE虽保留旧条目,但禁用新建 - Buffer Pool过小:热点页驻留时间短 → AHI建了又删 → 实际无效;过大则引发OS级swap → 整体延迟上升
要不要关掉AHI?什么时候关?
关AHI不是“优化”,而是规避其锁竞争和内存抖动。适合关的信号很明确:
- 监控发现
hash searches/s长期 innodb_hash_searches_btree远高于innodb_hash_searches - 高并发OLTP场景下,
show global status like 'innodb_row_lock_waits'陡增,同时hash_lock等待在PFS中可查 - 业务以范围查询、排序、JOIN为主,等值点查占比极低
- 执行
SET GLOBAL innodb_adaptive_hash_index = OFF后,TPS或p99延迟有可观改善
真正影响AHI效果的,从来不是开关本身,而是buffer pool是否稳住热点页、查询模式是否足够单一、并发压力是否压垮了那把全局hash_lock。











