談?wù)凪ySQL 索引徐绑,B+樹原理,以及建索引的幾大原則掸绞,第六彈

一、存儲引擎的比較

image.png

注:上面提到的B樹索引并沒有指出是B-Tree和B+Tree索引耕捞,但是B-樹和B+樹的定義是有區(qū)別的衔掸。
在 MySQL 中,主要有四種類型的索引俺抽,分別為:B-Tree 索引敞映, Hash 索引, Fulltext 索引和 R-Tree 索引磷斧。

B-Tree 索引是 MySQL 數(shù)據(jù)庫中使用最為頻繁的索引類型振愿,除了 Archive 存儲引擎之外的其他所有的存儲引擎都支持 B-Tree 索引。Archive 引擎直到 MySQL 5.1 才支持索引弛饭,而且只支持索引單個(gè) AUTO_INCREMENT 列冕末。

不僅僅在 MySQL 中是如此,實(shí)際上在其他的很多數(shù)據(jù)庫管理系統(tǒng)中B-Tree 索引也同樣是作為最主要的索引類型侣颂,這主要是因?yàn)?B-Tree 索引的存儲結(jié)構(gòu)在數(shù)據(jù)庫的數(shù)據(jù)檢索中有非常優(yōu)異的表現(xiàn)档桃。

一般來說, MySQL 中的 B-Tree 索引的物理文件大多都是以 Balance Tree 的結(jié)構(gòu)來存儲的憔晒,也就是所有實(shí)際需要的數(shù)據(jù)都存放于 Tree 的 Leaf Node(葉子節(jié)點(diǎn)) 藻肄,而且到任何一個(gè) Leaf Node 的最短路徑的長度都是完全相同的,所以我們大家都稱之為 B-Tree 索引拒担。

當(dāng)然嘹屯,可能各種數(shù)據(jù)庫(或 MySQL 的各種存儲引擎)在存放自己的 B-Tree 索引的時(shí)候會對存儲結(jié)構(gòu)稍作改造。如 Innodb 存儲引擎的 B-Tree 索引實(shí)際使用的存儲結(jié)構(gòu)實(shí)際上是 B+Tree从撼,也就是在 B-Tree 數(shù)據(jù)結(jié)構(gòu)的基礎(chǔ)上做了很小的改造州弟,在每一個(gè)Leaf Node 上面出了存放索引鍵的相關(guān)信息之外,還存儲了指向與該 Leaf Node 相鄰的后一個(gè) LeafNode 的指針信息(增加了順序訪問指針)低零,這主要是為了加快檢索多個(gè)相鄰 Leaf Node 的效率考慮呆馁。

InnoDB是Mysql的默認(rèn)存儲引擎(Mysql5.5.5之前是MyISAM)

可能對于沒有了解過索引的猿友這樣看這篇文章十分吃力,這類猿友有必要先對Mysql索引有個(gè)大體的了解毁兆。

接下來我們先看看B-樹浙滤、B+樹的概念。弄清楚气堕,為什么加了索引查詢速度會加快纺腊?

二畔咧、B-樹、B+樹概念

B樹

即二叉搜索樹:

  1. 所有非葉子結(jié)點(diǎn)至多擁有兩個(gè)兒子(Left和Right)揖膜;

  2. 所有結(jié)點(diǎn)存儲一個(gè)關(guān)鍵字誓沸;

  3. 非葉子結(jié)點(diǎn)的左指針指向小于其關(guān)鍵字的子樹,右指針指向大于其關(guān)鍵字的子樹壹粟;

如:


image.png

B-樹

是一種多路搜索樹(并不是二叉的):

  1. 定義任意非葉子結(jié)點(diǎn)最多只有M個(gè)兒子拜隧;且M>2;

  2. 根結(jié)點(diǎn)的兒子數(shù)為[2, M]趁仙;

  3. 除根結(jié)點(diǎn)以外的非葉子結(jié)點(diǎn)的兒子數(shù)為[M/2, M]洪添;

  4. 每個(gè)結(jié)點(diǎn)存放至少M(fèi)/2-1(取上整)和至多M-1個(gè)關(guān)鍵字;(至少2個(gè)關(guān)鍵字)

  5. 非葉子結(jié)點(diǎn)的關(guān)鍵字個(gè)數(shù)=指向兒子的指針個(gè)數(shù)-1雀费;

  6. 非葉子結(jié)點(diǎn)的關(guān)鍵字:K[1], K[2], …, K[M-1]干奢;且K[i] < K[i+1];

  7. 非葉子結(jié)點(diǎn)的指針:P[1], P[2], …, P[M]盏袄;其中P[1]指向關(guān)鍵字小于K[1]的子樹忿峻,P[M]指向關(guān)鍵字大于K[M-1]的子樹,其它P[i]指向關(guān)鍵字屬于(K[i-1], K[i])的子樹辕羽;

  8. 所有葉子結(jié)點(diǎn)位于同一層逛尚;
    如:(M=3)


    image.png

    B-樹的搜索,從根結(jié)點(diǎn)開始刁愿,對結(jié)點(diǎn)內(nèi)的關(guān)鍵字(有序)序列進(jìn)行二分查找黑低,如果命中則結(jié)束,否則進(jìn)入查詢關(guān)鍵字所屬范圍的兒子結(jié)點(diǎn)酌毡;重復(fù)克握,直到所對應(yīng)的兒子指針為空,或已經(jīng)是葉子結(jié)點(diǎn)枷踏;

B-樹的特性:
  • 關(guān)鍵字集合分布在整顆樹中菩暗;

  • 任何一個(gè)關(guān)鍵字出現(xiàn)且只出現(xiàn)在一個(gè)結(jié)點(diǎn)中;

  • 搜索有可能在非葉子結(jié)點(diǎn)結(jié)束旭蠕;

  • 其搜索性能等價(jià)于在關(guān)鍵字全集內(nèi)做一次二分查找停团;

  • 自動層次控制;
    由于限制了除根結(jié)點(diǎn)以外的非葉子結(jié)點(diǎn)掏熬,至少含有M/2個(gè)兒子佑稠,確保了結(jié)點(diǎn)的至少利用率。

所以B-樹的性能總是等價(jià)于二分查找(與M值無關(guān))旗芬,也就沒有B樹平衡的問題舌胶;

由于M/2的限制,在插入結(jié)點(diǎn)時(shí)疮丛,如果結(jié)點(diǎn)已滿幔嫂,需要將結(jié)點(diǎn)分裂為兩個(gè)各占M/2的結(jié)點(diǎn)辆它;刪除結(jié)點(diǎn)時(shí),需將兩個(gè)不足M/2的兄弟結(jié)點(diǎn)合并履恩;

B+樹

B+樹是B-樹的變體锰茉,也是一種多路搜索樹:

  1. 其定義基本與B-樹同,除了:

  2. 非葉子結(jié)點(diǎn)的子樹指針與關(guān)鍵字個(gè)數(shù)相同切心;

  3. 非葉子結(jié)點(diǎn)的子樹指針P[i]飒筑,指向關(guān)鍵字值屬于[K[i], K[i+1])的子樹(B-樹是開區(qū)間);

  4. 為所有葉子結(jié)點(diǎn)增加一個(gè)鏈指針绽昏;

  5. 所有關(guān)鍵字都在葉子結(jié)點(diǎn)出現(xiàn)协屡;
    如:(M=3)


    image.png

    B+的搜索與B-樹也基本相同,區(qū)別是B+樹只有達(dá)到葉子結(jié)點(diǎn)才命中(B-樹可以在非葉子結(jié)點(diǎn)命中)而涉,其性能也等價(jià)于在關(guān)鍵字全集做一次二分查找著瓶;

B+的特性:
  • 所有關(guān)鍵字都出現(xiàn)在葉子結(jié)點(diǎn)的鏈表中(稠密索引)联予,且鏈表中的關(guān)鍵字恰好是有序的啼县;

  • 不可能在非葉子結(jié)點(diǎn)命中;

  • 非葉子結(jié)點(diǎn)相當(dāng)于是葉子結(jié)點(diǎn)的索引(稀疏索引)沸久,葉子結(jié)點(diǎn)相當(dāng)于是存儲(關(guān)鍵字)數(shù)據(jù)的數(shù)據(jù)層季眷;

  • 更適合文件索引系統(tǒng);

三卷胯、建索引的幾大原則

  1. 最左前綴匹配原則子刮,非常重要的原則,mysql會一直向右匹配直到遇到范圍查詢(>窑睁、<挺峡、between、like)就停止匹配担钮,比如a = 1 and b = 2 and c > 3 and d = 4 如果建立(a,b,c,d)順序的索引橱赠,d是用不到索引的,如果建立(a,b,d,c)的索引則都可以用到箫津,a,b,d的順序可以任意調(diào)整狭姨。

  2. =和in可以亂序,比如a = 1 and b = 2 and c = 3 建立(a,b,c)索引可以任意順序苏遥,mysql的查詢優(yōu)化器會幫你優(yōu)化成索引可以識別的形式

  3. 盡量選擇區(qū)分度高的列作為索引,區(qū)分度的公式是count(distinct col)/count(*)饼拍,表示字段不重復(fù)的比例,比例越大我們掃描的記錄數(shù)越少田炭,唯一鍵的區(qū)分度是1师抄,而一些狀態(tài)、性別字段可能在大數(shù)據(jù)面前區(qū)分度就是0教硫,那可能有人會問司澎,這個(gè)比例有什么經(jīng)驗(yàn)值嗎欺缘?使用場景不同,這個(gè)值也很難確定挤安,一般需要join的字段我們都要求是0.1以上谚殊,即平均1條掃描10條記錄

  4. 索引列不能參與計(jì)算,保持列“干凈”蛤铜,比如from_unixtime(create_time) = ’2014-05-29’就不能使用到索引嫩絮,原因很簡單,b+樹中存的都是數(shù)據(jù)表中的字段值围肥,但進(jìn)行檢索時(shí)剿干,需要把所有元素都應(yīng)用函數(shù)才能比較,顯然成本太大穆刻。所以語句應(yīng)該寫成create_time = unix_timestamp(’2014-05-29’);

  5. 盡量的擴(kuò)展索引置尔,不要新建索引。比如表中已經(jīng)有a的索引氢伟,現(xiàn)在要加(a,b)的索引榜轿,那么只需要修改原來的索引即可

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市朵锣,隨后出現(xiàn)的幾起案子谬盐,更是在濱河造成了極大的恐慌,老刑警劉巖诚些,帶你破解...
    沈念sama閱讀 218,386評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件飞傀,死亡現(xiàn)場離奇詭異,居然都是意外死亡诬烹,警方通過查閱死者的電腦和手機(jī)砸烦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來绞吁,“玉大人幢痘,你說我怎么就攤上這事∠朴荆” “怎么了雪隧?”我有些...
    開封第一講書人閱讀 164,704評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長员舵。 經(jīng)常有香客問我脑沿,道長,這世上最難降的妖魔是什么马僻? 我笑而不...
    開封第一講書人閱讀 58,702評論 1 294
  • 正文 為了忘掉前任庄拇,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘措近。我一直安慰自己溶弟,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,716評論 6 392
  • 文/花漫 我一把揭開白布瞭郑。 她就那樣靜靜地躺著辜御,像睡著了一般。 火紅的嫁衣襯著肌膚如雪屈张。 梳的紋絲不亂的頭發(fā)上擒权,一...
    開封第一講書人閱讀 51,573評論 1 305
  • 那天,我揣著相機(jī)與錄音阁谆,去河邊找鬼碳抄。 笑死,一個(gè)胖子當(dāng)著我的面吹牛场绿,可吹牛的內(nèi)容都是我干的剖效。 我是一名探鬼主播,決...
    沈念sama閱讀 40,314評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼焰盗,長吁一口氣:“原來是場噩夢啊……” “哼璧尸!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起姨谷,我...
    開封第一講書人閱讀 39,230評論 0 276
  • 序言:老撾萬榮一對情侶失蹤逗宁,失蹤者是張志新(化名)和其女友劉穎映九,沒想到半個(gè)月后梦湘,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,680評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡件甥,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,873評論 3 336
  • 正文 我和宋清朗相戀三年捌议,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片引有。...
    茶點(diǎn)故事閱讀 39,991評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡瓣颅,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出譬正,到底是詐尸還是另有隱情宫补,我是刑警寧澤,帶...
    沈念sama閱讀 35,706評論 5 346
  • 正文 年R本政府宣布曾我,位于F島的核電站粉怕,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏抒巢。R本人自食惡果不足惜贫贝,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,329評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧稚晚,春花似錦崇堵、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,910評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至也搓,卻和暖如春棍辕,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背还绘。 一陣腳步聲響...
    開封第一講書人閱讀 33,038評論 1 270
  • 我被黑心中介騙來泰國打工楚昭, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人拍顷。 一個(gè)月前我還...
    沈念sama閱讀 48,158評論 3 370
  • 正文 我出身青樓抚太,卻偏偏與公主長得像,于是被迫代替她去往敵國和親昔案。 傳聞我的和親對象是個(gè)殘疾皇子尿贫,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,941評論 2 355

推薦閱讀更多精彩內(nèi)容