摘要:本期圖解我們?yōu)榇蠹医馕鲆幌率侨绾螛?gòu)建的。因此建立的第一關(guān)就是只為頻繁使用的索引樹建立。關(guān)卡該索引樹上的某個(gè)檢索條件要被經(jīng)常使用顯而易見,如果我們?yōu)榱艘粋€(gè)很少出現(xiàn)的檢索條件建立,肯定是入不敷出的。
Adaptive Hash Index(以下簡稱 AHI)估計(jì)是 MySQL 的各大特性中,大家都知道名字但最說不清原理的一個(gè)特性。本期圖解我們?yōu)榇蠹医馕鲆幌?AHI 是如何構(gòu)建的。
首先我們思考一下 AHI 是為了解決什么問題:
隨著 MySQL 單表數(shù)據(jù)量增大,(盡管 B+ 樹算法極好地控制了樹的層數(shù))索引 B+ 樹的層數(shù)會(huì)逐漸增多;
隨著索引樹層數(shù)增多,檢索某一個(gè)數(shù)據(jù)頁需要沿著 B+ 樹從上往下逐層定位,時(shí)間成本就會(huì)上升;
為解決檢索成本問題,MySQL 就想到使用某一種緩存結(jié)構(gòu):根據(jù)某個(gè)檢索條件,直接查詢到對(duì)應(yīng)的數(shù)據(jù)頁,跳過逐層定位的步驟。這種緩存結(jié)構(gòu)就是 AHI。
AHI 在實(shí)現(xiàn)上就是一個(gè)哈希表:從某個(gè)檢索條件到某個(gè)數(shù)據(jù)頁的哈希表,仿佛并不復(fù)雜,但其中的關(guān)竅在于哈希表不能太大(哈希表維護(hù)本身就有成本,哈希表太大則成本會(huì)高于收益),又不能太?。ㄌt緩存命中率太低,沒有任何收益)。
這就是 AHI(中文名:自適應(yīng)哈希索引)中"自適應(yīng)"的用途:建立一個(gè)"不大不小剛剛好"的哈希表。
本文主要討論 MySQL 是如何建立起一個(gè)"剛剛好"的 AHI 的,如圖 1 所示:需要經(jīng)歷三個(gè)關(guān)卡,才能為某個(gè)數(shù)據(jù)頁建立 AHI,之后的查詢才能使用到該 AHI。
我們逐個(gè)關(guān)卡來介紹:
AHI 是為某個(gè)索引樹建立的(當(dāng)該索引樹層數(shù)過多時(shí),AHI 才能發(fā)揮效用)。如果某索引只被使用一兩次,就為之建立 AHI,會(huì)導(dǎo)致 AHI 太多,維護(hù)成本高于收益。
因此建立 AHI 的第一關(guān)就是:只為頻繁使用的索引樹建立 AHI。
顯而易見,如果我們?yōu)榱艘粋€(gè)很少出現(xiàn)的檢索條件建立 AHI,肯定是入不敷出的。
在此我們插播一個(gè)新概念 hash info,hash info 是用來描述一次檢索的條件與索引匹配程度(即此次檢索是如何使用索引的)。建立AHI時(shí),就可以根據(jù)匹配程度,抽取數(shù)據(jù)中匹配的部分,作為 AHI 的鍵。
關(guān)卡 2 就是為了找到經(jīng)常使用的 hash info。hash info 包括以下三項(xiàng):
檢索條件與索引匹配的列數(shù)
第一個(gè)不匹配的列中,兩者匹配的字節(jié)數(shù)
匹配的方向是否從左往右進(jìn)行
我們通過一個(gè)例子來簡要介紹 hash info 中第一項(xiàng)。假設(shè)一張表 table1,其索引是(A1 A2)兩列構(gòu)成的索引:
如果檢索條件是(A1=1 and A2=1),那么此次檢索使用了該索引的最左兩列,hash info 就是(20true)
如果檢索條件是(A1=1) 那么此次檢索使用了該索引的最左一列,hash info 就是(10true)
關(guān)卡 2 就是為了找出經(jīng)常使用的 hash info,作為建立 AHI 的依據(jù)。
如果我們?yōu)楸碇兴袛?shù)據(jù)建立 AHI,那 AHI 就失去了緩存的意義:內(nèi)存已不足以存放其身軀,必然要放到磁盤上,那么其成本顯然已經(jīng)不低于收益。
回憶一下,AHI 是為了縮短 B+ 樹的查詢成本設(shè)計(jì)的,如果把自己再放到磁盤上,就得變成另一顆 B+ 樹(B+ 樹算法是處理磁盤查詢的高效結(jié)構(gòu)),如此循環(huán)往復(fù),嗚呼哀哉。
因此我們只能為表中經(jīng)常被查詢的部分?jǐn)?shù)據(jù)建立 AHI。所以關(guān)卡 3 的任務(wù)就是找出哪些數(shù)據(jù)頁是經(jīng)常被使用的數(shù)據(jù)頁。
終于可以開始建立 AHI 了 我們舉個(gè)例子說明如何建立 AHI。假設(shè)以上三個(gè)關(guān)卡的通關(guān)情況如下:
表 table1 具有 4 列:A1A2A3B1。具有兩個(gè)索引 Idx1(A1A2A3) 和 Idx2(B1)
關(guān)卡 1:選出的索引是 Idx1
關(guān)卡 2:選出的 hash info 是 (2 0 true) (很多查詢命中了 Idx1 的最左兩列)
關(guān)卡 3:選出了某個(gè)數(shù)據(jù)頁 P3,其中包含數(shù)據(jù) (1111) 和 (1222) 等等
那么建立 AHI 的過程是:在內(nèi)存中,為數(shù)據(jù)頁 P3 中的每一行數(shù)據(jù)建立索引
對(duì)于數(shù)據(jù)(1111),根據(jù) hash info,選取前兩列建立 AHI 的一項(xiàng):(11)的哈希值->P3
對(duì)于數(shù)據(jù)(1222),根據(jù) hash info,選取前兩列建立 AHI 的一項(xiàng):(12)的哈希值->P3
以此類推
我們終于可以 AHI 加速查詢了,假設(shè)查詢條件是 A1=1 and A2=2,其滿足條件:
命中了索引 Idx1
索引 Idx1 上的 hash info 是(2 0 true),查詢條件(A1=1 and A2=2)根據(jù) hash info 轉(zhuǎn)成(12)的哈希值
根據(jù)此哈希值在 AHI 中查詢,可查詢到數(shù)據(jù)頁為 P3
從以上過程可以看出,如果命中了 AHI,就可以跳過圖 2 中查詢索引樹的 4 個(gè)步驟,一次到位找到數(shù)據(jù)頁,提升性能。
我們回顧一下 MySQL 建立 AHI 的整個(gè)過程:
隨著數(shù)據(jù)量增大,索引樹變得越來越高,查詢數(shù)據(jù)頁成本變大
MySQL 引入 AHI 作為查詢數(shù)據(jù)頁的緩存,想降低查詢數(shù)據(jù)頁的成本
AHI 的"自適應(yīng)"想解決的問題是 緩存不能太大,也不能太小
AHI 建立的過程中,通過不斷限制條件,只為經(jīng)常使用的索引和經(jīng)常使用的數(shù)據(jù)頁建立緩存
理解了 AHI 的建立過程,在運(yùn)維過程中就更容易理解 AHI 的狀態(tài),我們簡要盤點(diǎn)一下 AHI 的運(yùn)維:
innodb_adaptive_hash_index_parts。凡是緩存都會(huì)涉及多個(gè)緩存消費(fèi)者間的鎖競爭。MySQL 通過設(shè)立多個(gè) AHI 分區(qū),每個(gè)分區(qū)使用獨(dú)立的鎖,來減少鎖競爭。
SHOW ENGINE INNODB STATUS。其中有 AHI 的每個(gè)分區(qū)的使用率和 AHI 的命中率。如果你的業(yè)務(wù) AHI 使用率過低,理解了 AHI 建立的原理后,就可以分析該業(yè)務(wù)為何不命中 AHI,來判斷業(yè)務(wù)是否合理,是否需要改變?cè)L問模式或者將數(shù)據(jù)冷熱隔離。也可以考慮關(guān)閉 AHI,減少 AHI 的維護(hù)成本。
在低版本 MySQL 上使用 AHI,先查閱 MySQL bug 列表。低版本是存在一些與 AHI 相關(guān)的影響業(yè)務(wù)的缺陷,在新版本上均已修復(fù),新版本 MySQL 可放心使用。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/126050.html
摘要:接下來我們要配置這個(gè)的端口,這樣他們才能運(yùn)行時(shí)端口號(hào)不沖突。問題指明不同的端口號(hào)訪問也太蠢了吧的確很蠢,所以我們要慢慢過渡學(xué)習(xí)。接下來我們學(xué)習(xí)用來進(jìn)行反向代理。阿里云的部分有一些配置的具體過程。 一、在linux上部署運(yùn)行多個(gè)tomcat 1、以前的我們 雖然說是在linux上,但是windows上也是同樣的道理,只不過我們服務(wù)器都是選用linux罷了。 原先,自己有多個(gè)項(xiàng)目需要部署在...
摘要:不同于個(gè)人面經(jīng),這份面經(jīng)具有普適性。我在前面的文章中也提到了應(yīng)該怎么做自我介紹與項(xiàng)目介紹,詳情可以查看這篇文章備戰(zhàn)春招秋招系列初出茅廬的程序員該如何準(zhǔn)備面試。是建立連接時(shí)使用的握手信號(hào)。它表示確認(rèn)發(fā)來的數(shù)據(jù)已經(jīng)接受無誤。 showImg(https://segmentfault.com/img/remote/1460000016972448?w=921&h=532); 該文已加入開源文...
閱讀 3580·2023-04-25 20:09
閱讀 3770·2022-06-28 19:00
閱讀 3115·2022-06-28 19:00
閱讀 3129·2022-06-28 19:00
閱讀 3230·2022-06-28 19:00
閱讀 2917·2022-06-28 19:00
閱讀 3104·2022-06-28 19:00
閱讀 2704·2022-06-28 19:00