InnoDB到底支不支持哈希索引,為啥不同的人說的不一樣?
繼續(xù)回答水友提問(最近問MySQL的多):
沈老師,我在網(wǎng)上看到不同的資料,有的說InnoDB支持哈希索引,有的說不支持,到底哪個(gè)是正確的呢?
對于InnoDB的哈希索引,確切的應(yīng)該這么說:
- InnoDB用戶無法手動(dòng)創(chuàng)建哈希索引,這一層上說,InnoDB確實(shí)不支持哈希索引;
- InnoDB會(huì)自調(diào)優(yōu)(self-tuning),如果判定建立自適應(yīng)哈希索引(Adaptive Hash Index, AHI),能夠提升查詢效率,InnoDB自己會(huì)建立相關(guān)哈希索引,這一層上說,InnoDB又是支持哈希索引的;
那什么是自適應(yīng)哈希索引(Adaptive Hash Index, AHI)呢?原理又是怎樣的呢?咱們先從一個(gè)例子開始。
不妨設(shè)有InnoDB數(shù)據(jù)表:t(id PK, name KEY, sex, flag)
畫外音:id是主鍵,name建了普通索引。
假設(shè)表中有四條記錄:
- 1, shenjian, m, A
- 3, zhangsan, m, A
- 5, lisi, m, A
- 9, wangwu, f, B
如上圖,通過前序知識(shí),容易知道InnoDB在主鍵id上會(huì)建立聚集索引(Clustered Index),葉子存儲(chǔ)記錄本身,在name上會(huì)建立普通索引(Secondary Index),葉子存儲(chǔ)主鍵值。
發(fā)起主鍵id查詢時(shí),能夠通過聚集索引,直接定位到行記錄。
- select * from t where name='ls';
發(fā)起普通索引查詢時(shí):
- 會(huì)先從普通索引查詢出主鍵(上圖右邊);
- 再由主鍵,從聚集索引上二次遍歷定位到記錄(上圖左邊)。
不管聚集索引還是普通索引,記錄定位的尋路路徑(Search Path)都很長。
在MySQL運(yùn)行的過程中,如果InnoDB發(fā)現(xiàn),有很多SQL存在這類很長的尋路,并且有很多SQL會(huì)命中相同的頁面(page),InnoDB會(huì)在自己的內(nèi)存緩沖區(qū)(Buffer)里,開辟一塊區(qū)域,建立自適應(yīng)哈希所有AHI,以加速查詢。
從這個(gè)層面上來說,InnoDB的自使用哈希索引,更像“索引的索引”,畢竟其目的是為了加速索引尋路。
既然是哈希,key是什么,value是什么?
- key是索引鍵值(或者鍵值前綴)。
- value是索引記錄頁面位置。
為啥叫“自適應(yīng)(adaptive)”哈希索引?
系統(tǒng)自己判斷“應(yīng)該可以加速查詢”而建立的,不需要用戶手動(dòng)建立,故稱“自適應(yīng)”。
系統(tǒng)會(huì)不會(huì)判斷失誤,是不是一定能加速?
不是一定能加速,有時(shí)候會(huì)誤判。 當(dāng)業(yè)務(wù)場景為下面幾種情況時(shí):
- 很多單行記錄查詢(例如passport,用戶中心等業(yè)務(wù))
- 索引范圍查詢(此時(shí)AHI可以快速定位首行記錄)
- 所有記錄內(nèi)存能放得下
AHI往往是有效的。
畫外音:任何脫離業(yè)務(wù)的技術(shù)方案,都是耍流氓。
當(dāng)業(yè)務(wù)有大量like或者join,AHI的維護(hù)反而可能成為負(fù)擔(dān),降低系統(tǒng)效率,此時(shí)可以手動(dòng)關(guān)閉AHI功能。
一個(gè)小知識(shí)點(diǎn),希望解答了這位水友的疑問。
知其然,知其所以然。
【本文為51CTO專欄作者“58沈劍”原創(chuàng)稿件,轉(zhuǎn)載請聯(lián)系原作者】