确认 mysql ahi 是否生效需查运行时状态:show engine innodb status 中 hash table size 非极小且 used cells > 0,同时 innodb_hash_searches / (innodb_hash_searches + innodb_non_hash_searches) 比值稳定高于 0.7。

怎么确认 MySQL 是否启用了 AHI
自适应哈希索引(AHI)默认开启,但只对满足特定访问模式的二级索引生效,不是所有查询都能用上。不能光看配置项,得查运行时状态。
-
SHOW VARIABLES LIKE 'innodb_adaptive_hash_index'返回ON仅表示功能未被禁用,不等于当前有哈希索引在工作 - 真正判断是否“起效”,要看
SHOW ENGINE INNODB STATUS\G输出里的Hash table size和used cells—— 如果Hash table size是 512 或 1024(极小),且used cells长期为 0,基本说明 AHI 没建起来 - AHI 只针对「等值查询 + 高频访问 + 单一二级索引前缀」的组合自动构建,范围查询、
ORDER BY、LIKE 'abc%'不触发
为什么开了 AHI 却没看到性能提升
AHI 不是缓存,也不是通用加速器;它是 InnoDB 在 buffer pool 内对「某几个热索引页」做的内存级哈希映射,命中后跳过 B+ 树遍历。但它的适用面很窄,且容易被干扰。
- 表数据频繁更新(尤其是该索引列)会导致 AHI 条目反复失效重建,反而增加 latch 开销
- 并发度高时,
adaptive hash index latch可能成为争用点 ——SHOW ENGINE INNODB STATUS里若看到大量pending hash latches,就是瓶颈信号 - 如果查询走的是联合索引但只用后缀列(如索引
(a,b),查询条件是WHERE b = ?),AHI 完全不生效 - buffer pool 太小或热数据分散,AHI 哈希表无法稳定驻留,建了也很快被淘汰
如何安全地关闭或动态调整 AHI
关闭 AHI 不需要重启,但必须注意它和查询模式的耦合性 —— 有些 OLTP 场景关掉后 QPS 反而下降 10%~15%,别盲目一刀切。
- 在线关闭:
SET GLOBAL innodb_adaptive_hash_index = OFF,立即生效,已建的哈希表会逐步释放 - 想观察影响,建议先在低峰期执行,并紧盯
innodb_row_lock_waits和innodb_buffer_pool_reads:若后者明显上升,说明原本靠 AHI 规避的磁盘读回来了 - MySQL 8.0.22+ 支持更细粒度控制:
innodb_adaptive_hash_index_parts可设为 8/16/32 分片,缓解 latch 争用,但前提是 buffer pool 足够大(≥32GB 推荐设 16)
监控 AHI 实际效果的关键指标
别只盯着 Hash table size,那个数字本身意义不大。重点看它和实际请求的匹配度。
- 每秒 AHI 查找次数:
SELECT VARIABLE_VALUE FROM performance_schema.global_status WHERE VARIABLE_NAME = 'Innodb_hash_searches' - 每秒 B+ 树查找次数:
SELECT VARIABLE_VALUE FROM performance_schema.global_status WHERE VARIABLE_NAME = 'Innodb_non_hash_searches' - 比值
Innodb_hash_searches / (Innodb_hash_searches + Innodb_non_hash_searches)稳定高于 0.7 才算 AHI 真正在扛流量;低于 0.2 基本可认为无效 - 注意:
Innodb_hash_searches包含失败查找(没命中哈希但走了 fallback),所以不能直接当命中率用











