MySQL之Adaptive Hash Index详解

news2024/10/1 3:32:26

前言

本文已收录在MySQL性能优化+原理+实战专栏,点击此处浏览更多优质内容。

在这里插入图片描述

目录

  • 一、MySQL InnoDB是否支持哈希索引?
    • 1.1 InnoDB不支持Hash Index
    • 1.2 InnoDB支持Hash Index
  • 二、Adaptive Hash Index的概念
  • 三、涉及Adaptive Hash Index的参数
    • 3.1 innodb_adaptive_hash_index
    • 3.2 innodb_adaptive_flushing
    • 3.3 innodb_adaptive_flushing_lwm
    • 3.4 innodb_adaptive_hash_index_parts
    • 小提示
  • 四、准备工作
  • 五、通过聚簇索引和普通索引访问记录的过
    • 5.1 聚簇索引访问记录过程
    • 5.2 普通索引访问记录过程
  • 六、通过Adaptive Hash Index访问记录的过程
  • 七 、Adaptive Hash Index状态监控
  • 八、Adaptive Hash Index 注意事项
    • 8.1 使用场景
    • 8.2 注意事项
    • 8.3 Adaptive Hash Index 限制

首先放一个MySQL官档中提供的InnoDB体系架构图:
在这里插入图片描述
如图所示,在InnoDB体系架构图的内存结构中,还有一块区域(已经用红框标出)名为:Adaptive Hash Index,翻译成中文:自适应哈希索引,缩写:AHI。它是一个纯内存结构,今天我们就来深入的了解它。

一、MySQL InnoDB是否支持哈希索引?

在网络上,流传着两种关于MySQL InnoDB哈希索引的传言。有一部分人说,InnoDB不支持哈希索引;有一部分人说,InnoDB支持哈希索引。那么到底谁说的对呢,其实两种说法都对

1.1 InnoDB不支持Hash Index

首先我们创建一张student表,代码如下:

mysql> create database testdb;
Query OK, 1 row affected (0.00 sec)

mysql> use testdb;
Database changed
mysql> create table student (  
student_id int not null auto_increment comment '学号',  
student_name varchar(20) not null comment '姓名',  
address varchar(100) default '江苏省苏州市常熟市' comment '家庭住址',  
primary key (student_id)  
) comment='学生表';
Query OK, 0 rows affected (0.03 sec)

然后,我们为address字段添加一个Hash Index

mysql> alter table student add index idx_address(address) using hash;
Query OK, 0 rows affected, 1 warning (0.05 sec)
Records: 0  Duplicates: 0  Warnings: 1

我们查看MySQL的warning

show warnings;
+-------+------+---------------------------------------------------------------------------------------------------------+
| Level | Code | Message                                                                                                 |
+-------+------+---------------------------------------------------------------------------------------------------------+
| Note  | 3502 | This storage engine does not support the HASH index algorithm, storage engine default was used instead. |
+-------+------+---------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

系统提示我们Innodb存储引擎不支持HASH索引算法,使用存储引擎默认值代替,接着查询创建完哈希索引后的表结构

mysql> show index from student \G;
*************************** 1. row ***************************
        Table: student
   Non_unique: 0
     Key_name: PRIMARY
 Seq_in_index: 1
  Column_name: student_id
    Collation: A
  Cardinality: 0
     Sub_part: NULL
       Packed: NULL
         Null: 
   Index_type: BTREE
      Comment: 
Index_comment: 
      Visible: YES
   Expression: NULL
*************************** 2. row ***************************
        Table: student
   Non_unique: 1
     Key_name: idx_address
 Seq_in_index: 1
  Column_name: address
    Collation: A
  Cardinality: 0
     Sub_part: NULL
       Packed: NULL
         Null: YES
   Index_type: BTREE
      Comment: 
Index_comment: 
      Visible: YES
   Expression: NULL
2 rows in set (0.01 sec)

ERROR: 
No query specified

从上面的显示结果看,你会惊人的发现,刚创建的Hash Index,终归还是B+树Index

1.2 InnoDB支持Hash Index

InnoDB会进行自调优,如果判定建立Adaptive Hash Index,能够提升查询效率,InnoDB自己会在内存中建立相关哈希索引(所以这就是Adaptive——“自适应”的由来),不需要人工手动干预,InnoDB会根据所需自己创建自适应哈希索引。所以,从这个角度来说,InnoDB是支持哈希索引的

二、Adaptive Hash Index的概念

自适应哈希索引是Innodb引擎的一个特殊功能,当它注意到某些索引值使用的非常频繁,发现建立哈希索引(又称散列索引)可以带来速度的提升,Innodb就会在自己的内存缓冲区(Buffer Pool)里,开辟一块区域,建立自适应哈希索引(Adaptive Hash Index,AHI),以便加速查询。

官档地址:https://dev.mysql.com/doc/refman/8.0/en/innodb-adaptive-hash.html
点击此处跳转

三、涉及Adaptive Hash Index的参数

show variables like '%adaptive%'

在这里插入图片描述

3.1 innodb_adaptive_hash_index

该参数影响自适应哈希索引是否启用。默认情况下启用此变量。当我们禁用自适应哈希索引会立即清空哈希表。当哈希表被清空时,正常操作可以继续,并且执行使用哈希表的查询直接访问索引 B 树。当重新启用自适应散列索引时,在正常操作期间会再次填充散列表。

set persist innodb_adaptive_hash_index = on;

3.2 innodb_adaptive_flushing

该参数影响每秒刷新脏页的操作,默认情况下是启用此变量,刷新脏页会通过判断产生重做日志的速度来判断最合适的刷新脏页的数量,如果关闭该参数会导致你的MySQL的服务器的tps有明显的波动。每当重做日志写满了,MySQL就会停下手头的任务,先把脏页刷到磁盘里,才能继续干活

set persist innodb_adaptive_flushing = on;

3.3 innodb_adaptive_flushing_lwm

该参数可以设置redo log flush低水位线,当需要flush的redo log超过这个低水位时,innodb会立即启用adaptive flushing,默认值10,最小值0,最大值70

set persist innodb_adaptive_flushing_lwm= 10;

3.4 innodb_adaptive_hash_index_parts

该参数是5.7后InnoDB将自适应哈希索引进行了分区处理,每个区对应一个锁,如果大量地访问,那么可能会对性能产生影响(抢锁),InnoDB将这个值默认设为8,最小值1,最大值512

set persist_only innodb_adaptive_hash_index_parts= 10;

小提示

相关参数解释了这么多,其实生产环境我们均采取默认值即可。

四、准备工作

为了后面内容的顺利进行,我们对student学生表做了一些改造

  • 删除了并没有实际用处的“Hash”索引idx_address
mysql> alter table student drop index idx_address;
  • 为student_name学生姓名字段添加了一个普通二级索引。
mysql> alter table student add index idx_student_name(student_name);
  • 为student_name插入数据
insert into student(student_name,address) values('张一','工业园区');
insert into student(student_name,address) values('张二','姑苏区');
insert into student(student_name,address) values('张三','吴中区');
insert into student(student_name,address) values('张四','高新区');
insert into student(student_name,address) values('张五','吴江区');
insert into student(student_name,address) values('张六','相城区');
insert into student(student_name,address) values('张七','常熟市');
insert into student(student_name,address) values('张八','昆山市');
insert into student(student_name,address) values('张九','太仓市');
insert into student(student_name,address) values('张十','张家港市');
  • 最后,我们看一下表结构和表中的数据
mysql> show create table student \G;
*************************** 1. row ***************************
       Table: student
Create Table: CREATE TABLE `student` (
  `student_id` int NOT NULL AUTO_INCREMENT COMMENT '学号',
  `student_name` varchar(20) NOT NULL COMMENT '姓名',
  `address` varchar(100) DEFAULT '江苏省苏州市常熟市' COMMENT '家庭住址',
  PRIMARY KEY (`student_id`),
  KEY `idx_student_name` (`student_name`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='学生表'
1 row in set (0.00 sec)

ERROR: 
No query specified

mysql> select * from student;
+------------+--------------+--------------+
| student_id | student_name | address      |
+------------+--------------+--------------+
|          1 | 张一         | 工业园区     |
|          2 | 张二         | 姑苏区       |
|          3 | 张三         | 吴中区       |
|          4 | 张四         | 高新区       |
|          5 | 张五         | 吴江区       |
|          6 | 张六         | 相城区       |
|          7 | 张七         | 常熟市       |
|          8 | 张八         | 昆山市       |
|          9 | 张九         | 太仓市       |
|         10 | 张十         | 张家港市     |
+------------+--------------+--------------+
10 rows in set (0.00 sec)

五、通过聚簇索引和普通索引访问记录的过

InnoDB中,表数据文件本身就是按B+Tree组织的一个索引结构,聚簇索引就是按照每张表的主键构造一颗B+树,同时叶子节点中存放的就是整张表的行记录数据,也将聚集索引的叶子节点称为数据页。这个特性决定了索引组织表中数据也是索引的一部分;

5.1 聚簇索引访问记录过程

student学生表中的数据我们可以简易画一个B+树的结构图(真实的B+树结构要复杂的多,后期会开辟单独的文章详细讲解),如下所示:
在这里插入图片描述
InnoDB会在主键student_id上建立聚集索引(Clustered Index),叶子节点存储记录本身,在student_name上会建立普通索引(Secondary Index),叶子节点存储主键值(聚集索引就是数据的完整记录,普通索引也是单独的物理结构,两者均存放在.ibd文件中)。发起主键student_id查询时,能够通过聚集索引,直接定位到行记录。

select * from student where student_id = 6;

此时的过程如下图所示:
在这里插入图片描述

5.2 普通索引访问记录过程

select * from student where student_name = '张九';

在这里插入图片描述
通过普通索引查询记录时,和通过聚簇索引查询记录有所不同,分为两步:

  • 步骤1:查询会先访问普通索引,定位到主键值9;
  • 步骤2:再通过步骤1得到的主键值,回表到聚集索引上经过二次遍历定位到具体的完整记录。

六、通过Adaptive Hash Index访问记录的过程

从上面的流程图可以看出,不管是聚集索引还是普通索引,记录定位的寻路路径(Search Path)都很长。回到Adaptive Hash Index的概念上:在MySQL运行的过程中,如果InnoDB发现:

  • 有很多寻路很长(比如B+树层数太多、回表次数多等情况)的SQL;
  • 有很多SQL会命中相同的页(Page)。

Innodb就会在自己的内存缓冲区(Buffer Pool)里,开辟一块区域,建立自适应哈希索引(Adaptive Hash Index,AHI),以便加速查询。

Adaptive Hash Index访问记录原理
在这里插入图片描述
通过上面的流程图,我们可以得出以下结论:

  • MySQL InnoDB的Adaptive Hash Index,更像“索引的索引”,以此来缩短寻路路径(Search Path)。
  • 我们都知道,Hash数据结构都是包含键(Key)、值(Value)的,在Adaptive Hash Index,Key就是经常访问到的索引键值,Value就是该索引键值匹配的完整记录所在页面(Page)的位置。
  • 因为是MySQL InnoDB自己维护创建的,所以称之为“自适应”哈希索引,但系统也有误判的时候,也不能起到加速查询的效果。

七 、Adaptive Hash Index状态监控

show engine innodb status \G;

在这里插入图片描述
注意: 这是一段时间的结果。通过hash searches、non-hash searches计算AHI带来的收益以及成本,确定是否开启AHI

八、Adaptive Hash Index 注意事项

8.1 使用场景

  • 很多单行记录查询,比如用户登录系统时密码的校验。
  • 索引范围查询,此时AHI可以快速定位首行记录。
  • 所有记录内存能放得下,这时AHI往往是有效的。
  • 当业务有大量LIKE或者JOIN,AHI的维护反而可能成为负担,降低系统效率,此时可以手动关闭AHI功能。

8.2 注意事项

  • AHI目的:缓存索引中的热点数据,提高检索效率,时间复杂度O(1) VS O(N)的差异;
  • 基于主键的搜索,几乎都是hash searches;
  • 基于普通索引的搜索,大部分是non-hash searches,小部分是hash searches;
  • 无序,没有树高,对热点Buffer Pool建立AHI,非持久化;
  • 初始化为innodb_buffer_pool_size的1/64,会随着InnoDB Buffer Pool动态调整;
  • 只支持等值查询(基于主键的等值查询AHI效果更好)
  • AHI很可能是部分长度索引,并非所有的查询都能有效果

8.3 Adaptive Hash Index 限制

  • 只能用于等值比较,例如=、<=>、IN、AND等
  • 无法用于排序
  • 有冲突可能
  • MySQL自动(“自适应”)管理,人为无法干预

今天主要讲解了MySQL InnoDB Adaptive Hash Index的工作原理,通过一些例子来说明整个过程,偏理论的知识,内容比较少也很好理解,大家理解记忆即可,面试中有被问到的可能。
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/485273.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

接口优化的策略

1.批处理 批量思想&#xff1a;批量操作数据库&#xff0c;这个很好理解&#xff0c;我们在循环插入场景的接口中&#xff0c;可以在批处理执行完成后一次性插入或更新数据库&#xff0c;避免多次IO。 //批量入库 batchInsert();List的安全操作有以下几种方式&#xff1a; 使…

DAY 50 LVS负载均衡器 NAT模式

群集概述 群集的含义 Cluster&#xff0c;集群、群集由多台主机构成&#xff0c;但对外只表现为一一个整体&#xff0c;只提供一-个访问入口(域名或IP地址)&#xff0c; 相当于一台大型计算机。 为什么使用群集 互联网应用中&#xff0c;随着站点对硬件性能、响应速度、服务…

Python学习日记(2)

有关数字类型&#xff0c;字符串&#xff0c;函数 目录 有关数字类型&#xff0c;字符串&#xff0c;函数 数字 字符串 索引操作 切片操作 单个字符编码 运算符 还有一些常用的内置函数 Python输入函数 输出函数print()语法 python的函数也能给默认值 Python是个脚…

C++系列一: C++简介

C入门简介 1. C语言的特点2. C编译器3. 第一个 C 程序4. 总结&#xff08;手稿版&#xff09; C 是一种高级编程语言&#xff0c;是C语言的扩展和改进版本&#xff0c;由Bjarne Stroustrup于1983年在贝尔实验室为了支持C语言中的面向对象编程而创建。C 既能够进行底层的系统编程…

全注解下的SpringIoc 续4-条件装配bean

Spring Boot默认启动时会加载bean&#xff0c;如果加载失败&#xff0c;则应用就会启动失败。但是部分场景下&#xff0c;我们希望某个bean只有满足一定的条件下&#xff0c;才允许Spring Boot加载&#xff0c;所以&#xff0c;这里就需要使用Conditional注解来协助我们达到这样…

二叉搜索树(BST)详解

文章目录 性质二叉搜索树的遍历遍历伪代码实现 二叉搜索树的查找伪代码实现 二叉搜索树最大元素伪代码实现 二叉搜索树最小元素伪代码实现 二叉搜索树的插入伪代码实现 二叉搜索树的删除删除叶子节点&#xff08;对应上面第一种情况&#xff09;&#xff1a;删除度为1的节点&am…

机械硬盘(HDD)与固态硬盘(SSD)

目录 机械硬盘&#xff08;HDD&#xff09; 最小组成单元是扇区 硬盘结构 硬盘工作原理 硬盘上的数据组织 硬盘指标 影响性能的因素 固态硬盘&#xff08;SSD&#xff09; 最小存储单元是Cell SSD的特点 SSD架构 NAND Flash 闪存介质 地址映射管理 FTL闪存转换层 机械硬盘&…

Python之模块和包(九)

1、模块 1、模块概述 模块是一个包含了定义的函数和变量等的文件。模块可以被程序引入&#xff0c;以使用该模块中的函数等功能。通俗讲&#xff1a;模块就好比是工具包&#xff0c;要想使用这个工具包中的工具(就好比函数)&#xff0c;就需要导入这个模块。 2、import 在P…

Redis分布式锁原理之实现秒杀抢优惠卷业务

Redis分布式锁原理之实现秒杀抢优惠卷业务 1. 实现秒杀下单2. 库存超卖问题分析2.1 乐观锁解决超卖问题 3. 优惠券秒杀-一人一单3.1 集群环境下的并发问题 4、分布式锁4.1 基本原理和实现方式对比4.2 Redis分布式锁的实现核心思路4.3 实现分布式锁版本一4.4 Redis分布式锁误删情…

【Java入门合集】第三章面向对象编程(上)

【Java入门合集】第三章面向对象编程&#xff08;上&#xff09; 博主&#xff1a;命运之光 专栏&#xff1a;JAVA入门 理解面向对象三大主要特征&#xff1b; 掌握类与对象的区别与使用&#xff1b; 掌握类中构造方法以及构造方法重载的概念及使用&#xff1b; 掌握包的定义、…

国民技术N32G430开发笔记(14)-IAP升级 usart2接收数据

IAP升级 Usart2接收数据 1、之前有一节我们将PA6 PA7复用成了usart2的功能&#xff0c;这一节我们用usart2接收来自树莓派的升级请求&#xff0c;然后完成N32G430的Iap升级。 2、接线 PA9 PA10 接usb转串口模块A&#xff0c;A模块插入电脑。 PA6 PA7 接usb转串口模块B&#xf…

【移动端网页布局】流式布局案例 ⑥ ( 多排按钮导航栏 | 设置浮动及宽度 | 设置图片样式 | 设置文本 )

文章目录 一、多排按钮导航栏样式及核心要点1、实现效果2、总体布局设计3、设置浮动及宽度4、设置图片样式5、设置文本 二、完整代码实例1、HTML 标签结构2、CSS 样式3、展示效果 一、多排按钮导航栏样式及核心要点 1、实现效果 要实现下面的导航栏效果 ; 2、总体布局设计 该导…

计算机网络笔记:DNS域名解析过程

基本概念 DNS是域名系统&#xff08;Domain Name System&#xff09;的缩写&#xff0c;也是TCP/IP网络中的一个协议。在Internet上域名与IP地址之间是一一对应的&#xff0c;域名虽然便于人们记忆&#xff0c;但计算机之间只能互相认识IP地址&#xff0c;域名和IP地址之间的转…

基于探路者算法的极限学习机(ELM)回归预测-附代码

基于探路者算法的极限学习机(ELM)回归预测 文章目录 基于探路者算法的极限学习机(ELM)回归预测1.极限学习机原理概述2.ELM学习算法3.回归问题数据处理4.基于探路者算法优化的ELM5.测试结果6.参考文献7.Matlab代码 摘要&#xff1a;本文利用探路者算法对极限学习机进行优化&…

算法 DAY45 动态规划07 70. 爬楼梯 322. 零钱兑换 279. 完全平方数 139. 单词拆分 多重背包

70. 爬楼梯 和377. 组合总和 Ⅳ (opens new window)基本就是一道题了。本题代码不长&#xff0c;题目也很普通&#xff0c;但稍稍一进阶就可以考察完全背包 class Solution { public:int climbStairs(int n) {vector<int> nums {1,2};vector<int> dp(n1,0);dp[0…

while语句和until语句顺便带点小实验

while语句和until语句 一、while用法二、Until循环语句三、趣味小实验猜价格的游戏&#xff08;价格是随机数&#xff09;写一个计算器脚本闲来无事去购物 一、while用法 for循环语句非常适用于列表对象无规律&#xff0c;且列表来源以固定&#xff08;如某个列表文件&#xf…

Android Studio开发图书管理系统APP

Android Studio开发项目图书管理系统项目视频展示&#xff1a; 点击进入图书管理系统项目视频 引 言 现在是一个信息高度发达的时代&#xff0c;伴随着科技的进步&#xff0c;文化的汲取&#xff0c;人们对于图书信息的了解与掌握也达到了一定的高度。尤其是学生对于知识的渴…

word构建基块:快速插入重复内容的高级剪切板

本文参考自 word录入技巧&#xff1a;如何用自动图文集快速插入重复内容 - 知乎 介绍 构建基块&#xff0c;它就是和剪切板一样&#xff0c;点一下就粘贴一份新的&#xff0c;用于解决大量重复内容的复制粘贴 构建基块包括自动图文集和快速表格&#xff0c;实际上都是构建基块…

Blender启动场景的修改

Blender启动场景的修改 1 使用版本2 现象描述3 解决方法4 启动场景路径5 清理场景资源5.1 空场景大小5.2 清理图片资源5.2.1 断开数据块关联5.2.2 断开伪用户关联5.2.3 断开多用户关联5.2.4 清理数据块5.2.6 文件校验 5.3 使用自建资源库 6 数据块类型 1 使用版本 Blender 3.3…

二叉树建立、遍历、打印(23春教学)

#include<stdio.h> #include <malloc.h> #include <conio.h> typedef char DataType; typedef struct Node {DataType data;struct Node *LChild;struct Node *RChild; }BitNode,*BitTree; void CreatBiTree(BitTree *bt)//用扩展先序遍历序列创建二叉树&am…