----->之前很多人還問我一些關於mysql索引的底層和使用,我就特意寫一篇文章跟大家一起分享一下我對mysql索引的理解,大家有更深入的理解可以下面留言。
1.索引的定義
MySQL官方對索引的定義為:索引(Index)是幫助MySQL高效獲取數據的數據結構
大家使用索引有沒有想過這個問題?為什么索引能夠幫助mysql高效獲取數據?我一一給大家道來!在給大家講之前,先更大家分享一些計算機基礎知識,有助於理解
-
我們都知道mysql數據是已文件的形式存儲在磁盤上的。
-
那磁盤是有一圈一圈的磁道組成的
-
磁頭移動到不同磁道,磁盤旋轉,這樣就可以讀取到數據
-
磁盤存取原理 1.尋道時間(速度慢,費時) 2.旋轉時間(速度較快)
-
cpu讀取數據都是從內存去讀,內存去磁盤讀取數據,內存讀取磁盤數據大小都是已頁的大小單位,一頁=10kb
總結:
-
通過上面的一些知識,我們知道當磁頭移動到另一個磁道讀取詩句就是我們常說的一次I/O操作,但是我們知道mysql數據是分布到不同的磁道上的,每次讀取數據都要把所有磁道讀取一遍,那我們進行I/O次數就很多了,查詢效率就很低
-
那索引就是把索引字段數據的地址保存起來,來幫助mysql直接定位到哪個磁道的哪個扇區,這樣就減少I/O操作了,自然查詢效率就提高了
2.數據結構那么多,mysql索引為什么要用B+Tree數據結構,而不是其他呢?肯定其他的數據不滿足我們的要求
常見的數據結構
1.二叉樹
2.紅黑樹
3.Hash
4.B Tree
5.B+Tree
a.二叉樹
二叉樹是n(n>=0)個結點的有限集合,該集合或者為空集(稱為空二叉樹),或者由一個根結點和兩棵互不相交的、分別稱為根結點的左子樹和右子樹組成。
不使用原因:會出現極端情況,一個節點只有一度,就是只有一個子節點,那讀取樹的一層就是一次I/O,那性能也不好
b.紅黑樹
紅黑樹即為平衡二叉樹的一種
不使用原因:極端情況下,一個節點有2個子節點,那就出現一層只有2個節點的情況,這種性能也不好
c.Hash
不使用原因:Hash是把索引數據進行Hash算法對應一個地址,我們會發現這個好像性能很好啊,直接找到,但是我們想想,它能滿足我們日常開發大部分情況嗎?比如通過大於或者小於去篩選數據,所以說也不合適,當然mysql還是提供了Hash索引,畢竟有些場合還是用起來也不錯
d.B Tree
1.度(Degree)-節點的數據存儲個數 2.葉節點具有相同的深度 3.葉節點的指針為空 4.節點中的數據key從左到右遞增排列
不使用原因:雖然解決了每一層的節點數的極端情況下,但是我們會發現每個節點存儲了索引和數據,那一層能存儲的數據太多也不好,畢竟內存能讀取的數據大小就是10kb
e.B+Tree
1.B+Tree(B-Tree變種) 2.非葉子節點不存儲data,只存儲key,可以增大度 3.葉子節點不存儲指針 4.順序訪問指針,提高區間訪問的性能
使用原因:設計有幾個方面 1.非葉子節點不存儲data,只存儲key,可以增大度 2.葉子節點不存儲指針 3.順序訪問指針,提高區間訪問的性能
3.B+Tree索引的性能分析
-
一般使用磁盤I/O次數評價索引結構的優劣
-
預讀:磁盤一般會順序向后讀取一定長度的數據(頁的整數倍)放入內存
-
局部性原理:當一個數據被用到時,其附近的數據也通常會馬上被使用
-
B+Tree節點的大小設為等於一個頁,每次新建節點直接申請一個頁的空間,這樣就保證一個節點物理上也存儲在一個頁里,就實現了一個節點的載入只需一次I/O
-
B+Tree的度d一般會超過100,因此h非常小(一般為3到5之間)
4.不同的存儲引擎有不同的索引實現
1.MyISAM索引實現(非聚集) 2.InnoDB索引實現(聚集)
a.MyISAM索引實現(非聚集)
--->MyISAM索引文件和數據文件是分離的
b.InnoDB索引實現(聚集)
1.數據文件本身就是索引文件 2.表數據文件本身就是按B+Tree組織的一個索引結構文件 3.聚集索引-葉節點包含了完整的數據記錄 4.為什么InnoDB表必須有主鍵,並且推薦使用整型的自增主鍵? 5.為什么非主鍵索引結構葉子節點存儲的是主鍵值?(一致性和節省存儲空間)
5.聯合索引結構
---->聯合索引的底層存儲結構長什么樣?