1:索引的本質
索引是什么?我們在學習數據庫的時候都會按照書本的目錄的方式來理解索引,其實索引就是一個幫助我們快速定位sql語句的排好序的數據結構。怎么理解尼?我們在學習查找算法的時候都知道,在查找有序序列的時候,采用二分法可以很快的查找對應元素,但是在數據庫中,如果不采用優化索引,只有一行一行的進行比較,才能找到元素,那索引如何工作的尼?
圖1.1
如上圖所示;我們執行左側的sql語句,如果我們,沒有對col2建立右側的索引數據結構,則該sql只能在表中,一行一行的檢查,比對col2是不是等於99,其平均的時間復雜度就是O(n),如果我們建立右側的二叉搜索樹,那么我們通過二叉搜索樹就能在O(logn)的時間內,完成一次查找,每一個節點里面都存放着該內容所在的位置。如果我們針對col1建立二叉搜索樹,很顯然,二叉樹會退化成鏈表的形式,依然是O(n)得時間復雜度,隨時大量數據的出現,將很慢,如下圖;
圖1.2
這就是二叉搜索樹作為索引的缺點和劣勢。索引的數據結構是怎么建立的尼?是隨着每次插入一條數據的時候,就會針對該數據不斷地完善索引數據結構。既然有序二叉排序樹不是平衡地二叉樹,如果我們采用紅黑樹(二叉平衡樹)地話,是不是就可以解決這個問題了尼?我們看下圖1.3
圖1.3
由於紅黑樹的自平衡特性,雖然輸入數據都是有序地,但是最終形成也是相對平衡地二叉樹。紅黑樹保證任意一個節點地左右兩邊的高度小於等於1。似乎可以解決不平衡帶來的問題。但是在數據庫索引中,依然沒有采用紅黑樹的原因尼?很顯然有部分應用場景紅黑樹還是步合適的,雖然紅黑樹是平衡的二叉樹,但是由於每一個節點處,只存放了一行數據,所以,當數據較多的時候,紅黑樹的高度依然會很高,所以依然不會采用紅黑樹!!!下面講解一種更合適的數據結構。
2:B+樹
如下圖2.1所示,就是一個B樹(多路平衡搜索樹)。每一個節點處存放多行元素,這樣就可以增加橫向的,降低高度,較少磁盤IO操作。
圖2.1
但是由於B樹的非葉子節點中依然存放部分數據,所以導致每一個節點的索引量依然不是很大,所以MySQL中對B樹設升級為B+樹,如下圖2.2所示
圖2.2
將非葉子節點中只存放索引,不存放數據,所以使得非葉子節點處能夠盡量存放更多的索引,使得樹的高度不會很高!這里的數據是指-該索引對應的行在磁盤的指針。同時上圖中B+樹有一個問題就是不同底層區間之間要用指針從左向右的相連(雙向指針),提高訪問速度!!!
下面針對MySQL中的特性,簡單分析一下高度為3的B+樹,大概可以存放多少條記錄?我們使用下面語句,可以知道Innodb中一個節點的大小為大概16KB。
SHOW GLOBAL STATUS LIKE 'Innodb_page_size';
那我們,假定每一個索引大小為8B,每一個指向下一個節點的指針為6B,那么在非葉子節點的每一個索引和指針都是成對出現的,所以大概每一個節點可以存放16KB/(8B+6B) = 1170個,即第一層的節點可以存放1170個指向下一層的指針,那第二層的指針個數尼?1170*1170 = 1368900個,第三層為葉子節點,其存放索引和數據,假設一個索引和數據的大小在一起為1KB,那么第三層為每一個節點處16個數據。所以該三層B+共可以索引到1170*1170*16條記錄,為21902400個,大概2千萬!也即是說2千萬條記錄,只需要一個3層的B+樹就可以進行索引了。
3:Myisam存儲引擎的特點
圖3.1
我們觀察Myisam存儲引擎的文件,會發現有3個文件分別是.MYF,.MYI和.MYD三個文件(非聚合)分別是Myisam的數據格式框圖文件,Myisam的索引文件以及Myisam的數據文件。我們以一條sql語句為例來分析。
select t.* from table t #假設col1列是建立索引的 where t.col1 = 99;
上圖語句,由於我們篩選條件col1是建立索引的了,所以會搜索在MYI文件里開始索引col1,按照B+樹進行索引,找到對應數據的磁盤指地址后,在從MYD文件中將數據load進來,即Myisam索引中存放的是相應數據的磁盤地址!
4:Innodb存儲引擎的特點
- 表數據文件本身就是一個B+樹組織的索結構文件
- 索引中葉子節點包含完整的數據記錄
- 為什么Innodb必須有用主鍵,並且推薦使用整形的自增當作索引?
- Innodb表,如果沒有認為建立主鍵,則軟件會找一列沒有重復數據的列作為主鍵列,建立B+樹的索引結構。如果沒有不重復的列,則MySQL會自動維護一列新的不重復列作為主鍵。
- 整形?因為在索引的過程中,要進行很多次比較和判斷,整形的比較顯然比字符型的要快呀。同時所在空間也小很多。
- 自增?我們觀察下圖,發現如果索引是遞增的,那么在范圍查找的時候,就會很方便,在葉子節點處,所有數據都是遞增的,只要索引處分界值的數據,通過下面的的節點之間的指針(雙向的指針)就可以很方便進行范圍查找。同時,還有一個原因,就是如果不是遞增的主鍵索引,那么在插入新的記錄的主鍵時B+樹為了實現非葉子節點的遞增順序,很有可能做一次分裂和平衡調整,顯然比遞增的操作要慢很多。
- 為什么非主鍵索引結構中,葉子節點處存放的是主鍵值?
- 一致性和節省空間
圖4.1
上圖4.1就是Innodb存儲引擎下的主鍵索引的結構,每一個葉子節點處都都對應者相應的記錄,聚合的。而相比於Myisam,在Innodb中每一個葉子節點處存放的就是對應行中數據記錄(Myisam中索引B+樹葉子節點存放的是對應數據行所在的磁盤地址)!
5:聯合索引
5.1:聯合索引底層存儲結構
