mysql从零单排之B+与AHI

MySQL InnoDB 缓冲池(Buffer Pool)中 B+ 树索引和自适应哈希索引(Adaptive Hash Index, AHI)的使用场景和区别。

核心概念

1. B+ 树索引(始终使用)

B+ 树是 InnoDB 的默认索引结构,所有数据都通过 B+ 树组织:

复制代码
┌─────────────────────────────────────────┐
│           非叶子节点(索引页)            │
│    存储键值 + 指向子节点的指针            │
├─────────────────────────────────────────┤
│           叶子节点(数据页)              │
│    存储实际数据行 + 指向相邻叶子的指针      │
└─────────────────────────────────────────┘

特点:

  • 范围查询友好:叶子节点形成有序链表
  • 磁盘友好:节点大小固定(通常 16KB),减少 I/O
  • 稳定性能:O(log N) 的查询复杂度
  • 支持顺序访问 :适合 BETWEENORDER BY 等操作

2. 自适应哈希索引(AHI)

AHI 是 建立在 B+ 树之上的内存优化结构,不是替代关系:

scss 复制代码
查询路径对比:

传统 B+ 树查询:          使用 AHI 加速后:
Root → 非叶子 → 叶子      Hash 直接定位 → 叶子
  (3-4 次页访问)          (1 次页访问)

使用场景对比

场景 使用结构 原因
所有数据存储 B+ 树 唯一持久化结构,必须存在
等值查询(=)且高频 B+ 树 + AHI AHI 加速热点页访问
范围查询(>/<) 仅 B+ 树 AHI 不支持范围
全表扫描 仅 B+ 树 顺序读取,无需索引
LIKE 模糊查询 仅 B+ 树 AHI 无法处理
联合索引前缀匹配 视情况而定 前缀不匹配时 AHI 失效

AHI 的触发条件

InnoDB 自动为 B+ 树页创建 AHI 条目,当满足:

markdown 复制代码
1. 页被访问多次(成为"热点页")
2. 访问模式是等值查询
3. 该页的访问方式稳定可预测

查看 AHI 状态:

sql 复制代码
SHOW ENGINE INNODB STATUS;
-- 关注 "INSERT BUFFER AND ADAPTIVE HASH INDEX" 部分

-- 关键指标:
-- - hash searches/s: 使用 AHI 的查询数
-- - non-hash searches/s: 回退到 B+ 树的查询数

配置与优化

ini 复制代码
# my.cnf 配置
[mysqld]
# 启用/禁用 AHI(默认开启)
innodb_adaptive_hash_index = ON

# 分区数量(减少锁竞争,高并发时有用)
innodb_adaptive_hash_index_parts = 8

关键理解

AHI 不是独立的索引类型,而是 B+ 树的"缓存加速器"

css 复制代码
┌─────────────────────────────────────┐
│           SQL 查询层                 │
│    SELECT * FROM t WHERE id = 100    │
└──────────────┬──────────────────────┘
               ▼
┌─────────────────────────────────────┐
│      优化器决定使用哪个索引            │
│    (基于成本模型选择 B+ 树索引)        │
└──────────────┬──────────────────────┘
               ▼
┌─────────────────────────────────────┐
│      访问 B+ 树索引结构               │
│    从根节点开始查找目标页              │
└──────────────┬──────────────────────┘
               ▼
┌─────────────────────────────────────┐
│    检查该页是否有 AHI 条目?          │
│    ├─ 有 → 直接通过 Hash 定位行       │
│    └─ 无 → 继续在 B+ 树中遍历         │
└─────────────────────────────────────┘

什么时候考虑关闭 AHI?

sql 复制代码
-- 高并发写入场景,AHI 维护成本可能超过收益
-- 如:大量并发 INSERT/UPDATE 导致频繁 AHI 重组

SET GLOBAL innodb_adaptive_hash_index = OFF;

关闭信号:

  • SHOW ENGINE INNODB STATUSnon-hash searches 远高于 hash searches
  • 观察到 btr_search_latch 锁竞争严重

总结

问题 答案
数据存在哪里? 始终在 B+ 树
等值查询如何加速? AHI 作为内存中的"快捷方式"
范围查询用什么? 只用 B+ 树
能手动创建 AHI 吗? 不能,完全自适应
删除 AHI 影响数据吗? 不影响,只是去掉加速层

AHI 是 InnoDB 的透明优化,你不需要(也无法)手动指定使用它,引擎会根据工作负载自动维护。

相关推荐
SomeB1oody8 小时前
【RustyML入门】6.3. 并行归约
开发语言·后端·机器学习·rust·教程
Profile排查笔记8 小时前
指纹浏览器哪个好?从 Profile、代理、权限和自动化能力判断是否适合
前端·人工智能·后端·自动化
用户938515635079 小时前
用 AI 结对编程从 0 搭一个"单词后台管理系统":Next.js + Supabase + Drizzle + shadcn/ui 全记录
后端·postgresql·next.js
爱学习的小邓同学9 小时前
Golang --- (1)第一个Golang程序
开发语言·后端·golang
小灰灰搞电子10 小时前
Rust+Slint 实现的“DNA双螺旋”加载动画源码分享
后端·rust·slint·加载动画
面向Google编程10 小时前
向量库不再囤数据:Milvus 3.0 零拷贝直读数据湖
后端
IT_陈寒12 小时前
Redis内存警告竟是因为这个不起眼的配置项
前端·人工智能·后端
Python私教12 小时前
AI 漫剧角色一进分镜就变脸?把提示词升级成“角色 ID + 镜头合同”
后端
Python私教12 小时前
一次生成 20 个角色却全都撞脸:我用“角色合同”重做了批量生成流程
后端
用户5944041035613 小时前
Go 语言高性能 Web 服务开发:基于 Gin + GORM + Redis 构建 RESTful API
后端