首页 > 其他分享 >Adaptive Hash Index 是如何建立的

Adaptive Hash Index 是如何建立的

时间:2023-08-02 14:12:23浏览次数:34  
标签:info Index 检索 Hash AHI 索引 哈希 hash Adaptive

Adaptive Hash Index(以下简称 AHI)估计是 MySQL 的各大特性中,大家都知道名字但最说不清原理的一个特性。本期图解我们为大家解析一下 AHI 是如何构建的。

 

首先我们思考一下 AHI 是为了解决什么问题:

 

  • 随着 MySQL 单表数据量增大,(尽管 B+ 树算法极好地控制了树的层数)索引 B+ 树的层数会逐渐增多;
  • 随着索引树层数增多,检索某一个数据页需要沿着 B+ 树从上往下逐层定位,时间成本就会上升;
  • 为解决检索成本问题,MySQL 就想到使用某一种缓存结构:根据某个检索条件,直接查询到对应的数据页,跳过逐层定位的步骤。这种缓存结构就是 AHI。

AHI 在实现上就是一个哈希表:从某个检索条件到某个数据页的哈希表,仿佛并不复杂,但其中的关窍在于哈希表不能太大(哈希表维护本身就有成本,哈希表太大则成本会高于收益),又不能太小(太小则缓存命中率太低,没有任何收益)。

这就是 AHI(中文名:自适应哈希索引)中"自适应"的用途:建立一个"不大不小刚刚好"的哈希表。

本文主要讨论 MySQL 是如何建立起一个"刚刚好"的 AHI 的,如图 1 所示:需要经历三个关卡,才能为某个数据页建立 AHI,之后的查询才能使用到该 AHI。

 

 


我们逐个关卡来介绍:

 

关卡 1:某个索引树要被使用足够多次AHI 是为某个索引树建立的(当该索引树层数过多时,AHI 才能发挥效用)。如果某索引只被使用一两次,就为之建立 AHI,会导致 AHI 太多,维护成本高于收益。因此建立 AHI 的第一关就是:只为频繁使用的索引树建立 AHI。

 

 

关卡 2:该索引树上的某个检索条件要被经常使用

 

显而易见,如果我们为了一个很少出现的检索条件建立 AHI,肯定是入不敷出的。

 

在此我们插播一个新概念 hash info,hash info 是用来描述一次检索的条件与索引匹配程度(即此次检索是如何使用索引的)。建立AHI时,就可以根据匹配程度,抽取数据中匹配的部分,作为 AHI 的键。关卡 2 就是为了找到经常使用的 hash info。hash info 包括以下三项:

 

  • 检索条件与索引匹配的列数
  • 第一个不匹配的列中,两者匹配的字节数
  • 匹配的方向是否从左往右进行

 

我们通过一个例子来简要介绍 hash info 中第一项。假设一张表 table1,其索引是(A1, A2)两列构成的索引:

 

  • 如果检索条件是(A1=1 and A2=1),那么此次检索使用了该索引的最左两列,hash info 就是(2,0,true)
  • 如果检索条件是(A1=1), 那么此次检索使用了该索引的最左一列,hash info 就是(1,0,true)

 

关卡 2 就是为了找出经常使用的 hash info,作为建立 AHI 的依据。

 

 

关卡 3:该索引树上的某个数据页要被经常使用如果我们为表中所有数据建立 AHI,那 AHI 就失去了缓存的意义:内存已不足以存放其身躯,必然要放到磁盘上,那么其成本显然已经不低于收益。回忆一下,AHI 是为了缩短 B+ 树的查询成本设计的,如果把自己再放到磁盘上,就得变成另一颗 B+ 树(B+ 树算法是处理磁盘查询的高效结构),如此循环往复,呜呼哀哉。

 

因此我们只能为表中经常被查询的部分数据建立 AHI。所以关卡 3 的任务就是找出哪些数据页是经常被使用的数据页。

 

 


 

修成正果:终于开始建立 AHI终于可以开始建立 AHI 了, 我们举个例子说明如何建立 AHI。假设以上三个关卡的通关情况如下:

 

  • 表 table1 具有 4 列:A1,A2,A3,B1。具有两个索引 Idx1(A1,A2,A3) 和 Idx2(B1)
  • 关卡 1:选出的索引是 Idx1
  • 关卡 2:选出的 hash info 是 (2, 0, true) (很多查询命中了 Idx1 的最左两列)
  • 关卡 3:选出了某个数据页 P3,其中包含数据 (1,1,1,1) 和 (1,2,2,2) 等等

 

那么建立 AHI 的过程是:在内存中,为数据页 P3 中的每一行数据建立索引

 

  • 对于数据(1,1,1,1),根据 hash info,选取前两列建立 AHI 的一项:(1,1)的哈希值->P3
  • 对于数据(1,2,2,2),根据 hash info,选取前两列建立 AHI 的一项:(1,2)的哈希值->P3
  • 以此类推

 

普度众生:终于可以使用 AHI我们终于可以 AHI 加速查询了,假设查询条件是 A1=1 and A2=2,其满足条件:

 

  • 命中了索引 Idx1
  • 索引 Idx1 上的 hash info 是(2, 0, true),查询条件(A1=1 and A2=2)根据 hash info 转成(1,2)的哈希值
  • 根据此哈希值在 AHI 中查询,可查询到数据页为 P3

 

从以上过程可以看出,如果命中了 AHI,就可以跳过图 2 中查询索引树的 4 个步骤,一次到位找到数据页,提升性能。

 


 

总结我们回顾一下 MySQL 建立 AHI 的整个过程:

 

  • 随着数据量增大,索引树变得越来越高,查询数据页成本变大
  • MySQL 引入 AHI 作为查询数据页的缓存,想降低查询数据页的成本
  • AHI 的"自适应"想解决的问题是 缓存不能太大,也不能太小
  • AHI 建立的过程中,通过不断限制条件,只为经常使用的索引和经常使用的数据页建立缓存

 

运维建议理解了 AHI 的建立过程,在运维过程中就更容易理解 AHI 的状态,我们简要盘点一下 AHI 的运维:

 

  • innodb_adaptive_hash_index_parts。凡是缓存都会涉及多个缓存消费者间的锁竞争。MySQL 通过设立多个 AHI 分区,每个分区使用独立的锁,来减少锁竞争。
  • SHOW ENGINE INNODB STATUS。其中有 AHI 的每个分区的使用率和 AHI 的命中率。如果你的业务 AHI 使用率过低,理解了 AHI 建立的原理后,就可以分析该业务为何不命中 AHI,来判断业务是否合理,是否需要改变访问模式或者将数据冷热隔离。也可以考虑关闭 AHI,减少 AHI 的维护成本。
  • 在低版本 MySQL 上使用 AHI,先查阅 MySQL bug 列表。低版本是存在一些与 AHI 相关的影响业务的缺陷,在新版本上均已修复,新版本 MySQL 可放心使用。
    • 转载自杨奇龙公众号

标签:info,Index,检索,Hash,AHI,索引,哈希,hash,Adaptive
From: https://www.cnblogs.com/lovezhr/p/17600521.html

相关文章

  • PHPHashtable 如何优化数组查找和排序
    PHPHashtable如何优化数组查找和排序PHP是一种高度流行的编程语言,被广泛用于web开发。它有很多的优点,例如易于学习、跨平台、简单易用的语法等等。而在PHP中,数组是一种非常常用的数据结构,它可以存储一组有序的数据,方便我们进行各种操作。PHPHashtable如何优化数组查找和排......
  • MySQL字符串截取之substring_index
    substring_index(str,delim,count)str:要处理的字符串delim:分隔符count:计数 例子:str=www.wikibt.comsubstring_index(str,'.',1)结果是:wwwsubstring_index(str,'.',2)结果是:www.wikibt也就是说,如果count是正数,那么就是从左往右数,第N个分隔符的左边的全部内容相......
  • 白话解析:一致性哈希算法 consistent hashing
    在了解一致性哈希算法之前,最好先了解一下缓存中的一个应用场景,了解了这个应用场景之后,再来理解一致性哈希算法,就容易多了,也更能体现出一致性哈希算法的优点,那么,我们先来描述一下这个经典的分布式缓存的应用场景。场景描述假设,我们有三台缓存服务器,用于缓存图片,我们为这三台......
  • 负载均衡算法: 简单轮询算法, 平滑加权轮询, 一致性hash算法, 随机轮询, 加权随机轮询
    直接上干活/***@version1.0.0*@@menu<p>*@date2020/11/1716:28*/publicclassLoadBlance{staticMap<String,Integer>serverWeightMap=newHashMap<>();static{serverWeig......
  • 什么是散列函数?HashMap 的实现原理是什么?
    散列函数(HashFunction)是一种将输入数据(通常是任意大小的数据)映射为固定大小散列值(哈希值)的函数。散列函数的目标是将数据均匀地映射到哈希值域,以便在哈希表等数据结构中高效地查找、插入和删除数据。好的散列函数应该尽可能避免冲突(即不同的输入映射到相同的哈希值),并具有良好的性......
  • HashMap源码
    put方法finalVputVal(inthash,Kkey,Vvalue,booleanonlyIfAbsent,booleanevict){Node<K,V>[]tab;Node<K,V>p;intn,i;//这个p是开始定位到的Node或者TreeNodeif((tab=table)==null||(n=tab.length)==0)//如果数组是n......
  • HashMap深入学习
    1.HashMap和HashTable的区别?a.HashMap是线程不安全的,HashTable是线程安全的。b.HashTable不允许有null键和null值。c.HashMap底层是数组+链表+红黑树,而HashTable底层是数组+链表。d.HashMap默认的初始大小为16,每次扩容变为原来的2倍;HashTable默认初始大小为11,每次扩容后容量变为原......
  • SQLite的SQL语法 CREATE INDEX
    SQLite的SQL语法[目录]CREATEINDEXsql-statement ::=CREATE[UNIQUE]INDEX[IFNOTEXISTS][database-name.]index-nameONtable-name(column-name[,column-name]*)column-name ::=name[COLLATEcollation-name][ASC|DESCCREATEINDEX命令由"CREATEINDEX&qu......
  • ES保存数据时报错:Bulk indexing has failures
    ElasticSearch保存时报错问题解决:错误信息org.springframework.data.elasticsearch.ElasticsearchException:Bulkindexinghasfailures.UseElasticsearchException.getFailedDocuments()fordetailedmessages解决:我这边是因为磁盘空间不足了,ES在分片分配时,默认不......
  • boost multi index多索引容器
    复制源:https://www.cnblogs.com/sssblog/p/11004572.html(纯英文)注意:本文是机翻Boost.MultiIndexmakesitpossibletodefinecontainersthatsupportanarbitrarynumberofinterfaces.Whilestd::vectorprovidesaninterfacethatsupportsdirectaccesstoelemen......