MySQL 12 深入理解MySQL索引底層數據結構與算法

MySQL實戰 目錄

前言

磁盤存取時間

  • 尋道時間(速度慢,費時)
  • 旋轉時間(速度較快)


    image.png

    image.png
局部性原理與磁盤預讀

為了提升效率,要盡量減少磁盤IO的次數。實際過程中,磁盤并不是每次嚴格按需讀取,而是每次都會預讀。磁盤讀取完需要的數據后,會按順序再多讀一部分數據到內存中,這樣做的理論依據是計算機科學中注明的局部性原理:

當一個數據被用到時,其附近的數據也通常會馬上被使用

程序運行期間所需要的數據通常比較集中
(1)由于磁盤順序讀取的效率很高(不需要尋道時間,只需很少的旋轉時間),
因此對于具有局部性的程序來說,預讀可以提高I/O效率.預讀的長度一般為頁(page)的整倍數。
(2)MySQL(默認使用InnoDB引擎),將記錄按照頁的方式進行管理,每頁大小默認為16K(這個值可以修改)。linux 默認頁大小為4K。

1. 索引到底是什么

索引是幫助MySQL高效獲取數據的排好序數據結構
索引存儲在文件里
索引結構

可視化數據結構演示

為什么不用二叉樹、紅黑樹、HASH 作為索引結構

二叉樹 數據向一方偏離,一個節點的左鍵點小于該節點,右節點大于該節點,但是如果插入二叉樹的數據是有序的,就會形成二叉樹的極端情況,形成鏈表,我們知道樹的查詢復雜度跟樹的高度有關,樹越高,那么查詢事件復雜度就越高,并且需要更多的磁盤IO,所以需要通過某種約束來保證樹的平衡,
紅黑樹

雖然數據較二叉樹樹形能翻轉保持平衡,數據大量的時候,數據深度會很大
紅黑樹就是平衡二叉樹中的一種,它通過一系列的規則來保證樹的平衡。但是在大規模數據存儲的時候,紅黑樹常常會因為樹的深度過高而導致磁盤IO讀寫過于頻繁,導致效率底下,為什么會形成這種情況呢,我們知道要獲取磁盤上的數據,必須通過磁盤移動臂移動到數據所在的柱面,然后找到指定盤面,接著旋轉盤面找到數據所在的磁道,最后進行讀寫,這種涉及到物理操作情況下,性能自然會很低下。
HASH

1.hash表只能匹配是否相等,不能實現范圍查找
select * from xx where id > 23; 這時就沒辦法索引了
2.當需要按照索引進行order by時,hash值沒辦法支持排序
select * from xx order by score desc;如果score為建立索引的字段,hash值沒辦法輔助排序。
3.組合索引可以支持部分索引查詢,如(a,b,c)的組合索引,查詢中只用到了阿和b也可以查詢的,如果使用hash表,組合索引會將幾個字段合并hash,沒辦法支持部分索引
4.當數據量很大時,hash沖突的概率也會非常大

一般來說有多少層高(數據深度)就有多少次IO耗時操作,減少層高非常有必要
BTree

  • 度(Degree)一節點的數據存儲個數
  • 葉子節點具有相同的深度
  • 葉子節點的指針為空
  • 節點中的數據key從左到右遞增排列
    注意:由于計算機硬件限制,度(Degree)無限增大,并不能減少IO次數


    image.png

B+Tree(B-Tree上優化)

  • 非葉子節點不存儲data,只儲存key,可以增大度(Degree)
  • 葉子節點不存儲指針
  • 順序訪問指針,提高區間訪問的性能


    image.png

B+Tree索引的性能分析

  • 一般使用磁盤I/O次數評價索引結構的優劣
  • 預讀:磁盤一般會順序向后讀取一定長度的數據(頁的整數倍)放入內存
  • 局部性原理:當一個數據被用到時,其附近的數據也通常會馬上被使用
  • B+Tree節點的大小設為等于一個頁,每次新建節點直接申請一個頁的空間,這樣就保證一個節點物理上也存儲在一個頁里,就實現了一個節點的載入只需一次I/O
  • B+Tree的度d一般會超過100,因此h非常小(一般為3到5之間)
為什么mysql的索引使用B+樹而不是B樹呢??

上面大致介紹了B-樹,B+樹,哈希索引。那么B+樹的優勢大致總結如下

  • 不同于B-樹只適合隨機檢索,B+樹同時支持隨機檢索和順序檢索;
  • B+樹的磁盤讀寫代價更低。B+樹內部結點比B-樹小,盤塊能容納的結點中關鍵字數量更多,一次性讀入內存中可以查找的關鍵字也就越多,相對的,IO讀寫次數也就降低了。而IO讀寫次數是影響索引檢索效率的最大因素。
  • B+樹的查詢效率更加穩定。B-樹搜索有可能會在非葉子結點結束,越靠近根節點的記錄查找時間越短,只要找到關鍵字即可確定記錄的存在,其性能等價于在關鍵字全集內做一次二分查找。而在B+樹中,順序檢索比較明顯,隨機檢索時,任何關鍵字的查找都必須走一條從根節點到葉節點的路,所有關鍵字的查找路徑長度相同,導致每一個關鍵字的查詢效率相當。
  • B-樹在提高了磁盤IO性能的同時并沒有解決元素遍歷的效率低下的問題。B+樹的葉子節點使用指針順序連接在一起,只要遍歷葉子節點就可以實現整棵樹的遍歷。而且在數據庫中基于范圍的查詢是非常頻繁的,而B-樹不支持這樣的操作(或者說效率太低)。


    image.png

2. MySQL數據庫存儲引擎

MyISAM索引實現(非聚集)

MyISAM索引文件和數據文件是分離的
image.png

image.png

有些 MySQL 版本還缺乏完整的存儲過程支持 — 意味著不支持事務,這是 MyISAM 系統的最大缺點。

InnoDB索引實現(聚集)

  • 數據文件本身就是索引文件
  • 表數據文件本身就是按B+Tree組織的一個索引結構文件
  • 聚集索引-葉節點包含了完整的數據記錄

為什么InnoDB表必須有主鍵,并且推薦使用整型的自增主鍵?

首先,為了滿足MySQL的索引數據結構B+樹的特性,必須要有索引作為主鍵,可以有效提高查詢效率,因此InnoDB必須要有主鍵。如果不手動指定主鍵,InnoDB會從插入的數據中找出不重復的一列作為主鍵索引,如果沒找到不重復的一列,這時候InnoDB會選擇內置的ROWID作為主鍵,寫入順序和ROWID增長順序一致;
其次,索引的數據類型是整型,一方面整型占有的磁盤空間或內存空間相比字符串更少,另一方面整型比較比字符串比較更快速,字符串比較是先轉換為ASCII碼,然后再比較的。
最后,B+樹本質是多路多叉樹,如果主鍵索引不是自增的,那么后續插入的索引就會引起B+樹的其他節點的分裂和重新平衡,影響數據插入的效率,如果是自增主鍵,只用在尾節點做增加就可以。

  • 為什么非主鍵索引結構葉子節點存儲的是主鍵值?(一致性和節省存儲空間)

主鍵索引和非主鍵索引維護各自的B+樹結構,當插入的數據的時候,由于數據只有一份,通過非主鍵索引獲取到主鍵值,然后再去主鍵索引的B+樹數據結構中找到對應的行數據,節省了內存空間;
如果非主鍵索引的葉子節點也存儲一份數據,如果通過非主鍵索引插入數據,那么要向主鍵索引對應的行數據進行同步,那么會帶來數據一致性問題。可以通過事務的方式解決,我們都知道使用事務后,就會對性能有所消耗。

image.png
image.png

image.png

聯合索引結構

聯合索引的底層存儲結構長什么樣?

定義聯合索引(員工級別,員工姓名,員工出生年月),將聯合索引按照索引順序放入節點中,新插入節點時,先按照聯合索引中的員工級別比較,如果相同會按照是員工姓名比較,如果員工級別和員工姓名都相同 最后是員工的出生年月比較。可以從圖中從上到下,從左到右看,第一個B+樹的節點 是通過聯合索引的員工級別比較的,第二個節點是 員工級別相同,會按照員工姓名比較,第三個節點是 員工級別和員工姓名都相同,會按照員工出生年月比較。


image.png
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,533評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,055評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,365評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,561評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,346評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,889評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,978評論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,118評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,637評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,558評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,739評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,246評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,980評論 3 346
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,362評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,619評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,347評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,702評論 2 370