之前為了搞清楚這塊問題,看了很多文章都寫的迷迷糊糊的,我盡量寫的簡單明瞭一點,包看懂就好。
先來思考索引的幾個問題?
1. 為什麼要給表加上主鍵?
2. 為什麼加索引後會使查詢變快?
3. 為什麼加索引後會使寫入、修改、刪除變慢?
4. 什麼情況下要同時在兩個欄位上建索引?
帶著問題我們接下來看,索引是什麼?它的底層是如何的相信你會有個不一樣的體會。
1、索引
是幫助mysql高效獲取資料的排好序的資料結構。
核心在於:排好序、資料結構。既然是資料結構我們肯定是要**下它的原理。
下面舉個例子:來看看索引的好處。下面有張表t,又圖是以col2作為索引的二叉樹資料結構,為什麼這裡用二叉樹建立索引,你可以理解為這個是mysql索引初期的樣子。
現在我們要對錶t,查詢col2=89的資料,sql語句為:select * from t where t.col2=89 limit 1
如果不加索引的話從表裡面一條條往下查,需要查詢6次才可以找到。經過了6次磁碟i/o,效率不高。
如果對col2建立了索引了之後,索引的資料結構如上面二叉樹的結構。第一次跟根節點34比較,比它大繼續向右查詢,查詢89只需要兩次。查詢次數相比之前減少了很多。效率也就提高了。以上的這種問題加索引後會使查詢變快的例子。
接下來我們討論下索引的資料結構演變過程。
2、索引資料結構
二叉樹紅黑樹
hash表
b-tree
1、先來說下二叉樹作為索引會怎麼樣?可以理解為初期的索引結構
假如我們要對上圖col1做為索引字段。會怎麼樣?
如果是此類資料的話,二叉樹形成了乙個執行緒結構,類似成乙個單向的鍊錶了,查詢效率o(n)。查詢葉子節點居然需要6次i/o,僅僅6行資料就要6次,如果上百萬資料那這種結構肯定是不合理的。
2、為了優化二叉樹的這種情況,優化之後使用紅黑樹(一種平衡的二叉樹,為何叫平衡的二叉樹,因為再往裡面加元素的時候,二叉樹多了乙個自旋的過程,避免出現二叉樹裡面的單向結構。)
相比於二叉樹,多了一步自旋平衡的乙個過程。但是索引並沒有選擇這種機構,為什麼?
6行資料,要經過4次的磁碟i/o。如果幾百萬資料,深度如何?所以後面的優化應該降低這個樹的高度,減少磁碟i/o的次數。
下圖舉個例子,100w資料如果插進去,高度差不多20。
紅黑樹作為索引資料結構的問題:資料量太大,高度就太深,如果查詢葉子節點的資料,查詢磁碟索引i/o非常慢。
3、hash表
對索引欄位做hash計算,經過一次磁碟i/o就可以查到資料。
hash表相當是乙個陣列,索引欄位做hash計算時相當與拿到資料的下標位置,然後根據這個位置直接找到元素,資料快時間複雜度o(1),效率很高。但是雜湊索引不支援範圍查詢和排序的功能。
4、b+樹(索引的底層資料結構)
在介紹b+樹之前,先看下b樹,b+樹是b樹的乙個演變。
b樹:根節點至少包括2個孩子
每個節點最多含m個子節點
b+樹:(b樹的變種)
1. 非葉子節點不儲存data,只儲存索引,可以放更多的索引
2. 葉子節點不儲存指標
3. 順序訪問指標,提高區間訪問的效能
根據結構來對比下,b+tree對比btree的優點:
1、磁碟讀寫代價更低
一般來說b+tree比btree更適合實現外存的索引結構,因為儲存引擎的設計專家巧妙的利用了外存(磁碟)的儲存結構,即磁碟的最小儲存單位是扇區(sector),而作業系統的塊(block)通常是整數倍的sector,作業系統以頁(page)為單位管理記憶體,一頁(page)通常預設為4k,資料庫的頁通常設定為作業系統頁的整數倍。
我們看下mysql預設設定的索引節點的大小:(innodb資料頁大小)
mysql預設的索引節點大小16k,因為mysql預設引擎innodb,所以這裡展示的是innodb預設的索引節點的大小。舉個例子存乙個bigint欄位,欄位佔8位元組(8b),加個指標(6b),那麼乙個索引節點可以儲存16k/(14b)~=1170個元素節點。樹的高度為3,以為著可能儲存1170個元素節點,再加入我們的葉子節點+索引大小為1k。那麼可以儲存1170117016個元素節點,相當與2000萬資料。支撐千萬級儲存
那麼可以知道,每個節點中的key個數越多,那麼樹的高度越小,需要i/o的次數越少,因此一般來說b+tree比btree更快,因為b+tree的非葉節點中不儲存data,就可以儲存更多的key。
mysql設定16k的大小,data元素。設定16k大小?希望這個樹可以儲存更多的元素。
2、查詢速度更穩定
由於b+tree非葉子節點不儲存資料(data),因此所有的資料都要查詢至葉子節點,而葉子節點的高度都是相同的,因此所有資料的查詢速度都是一樣的。
相信經過上面的介紹應該知道原理了,那麼我們在回頭看看之前的4個問題。
為什麼要給表加上主鍵?
為什麼加索引後會使查詢變快?
為什麼加索引後會使寫入、修改、刪除變慢?
什麼情況下要同時在兩個欄位上建索引?
是不是隱隱約約知道了一點原理?心裡有點想法的話,應該是這樣的
1、這裡主鍵可能就是索引
2、加了索引對資料進行了排序,肯定要比沒排序的要快
3、加索引新增資料的時候,怎麼保持樹的平衡結構,左節點《根節點《右節點。既然要保持這種結構資料增刪改肯定需要花費代價去維護索引的關係
4、可能還沒想法,沒事我們看下一章
資料結構索引 InnoDB索引
我們知道,myisam索引檔案和資料檔案是分離的,索引檔案僅僅儲存了資料記錄的位址。在innodb中,資料檔案本身就是索引檔案,表檔案本身就是乙個按照b 樹組織的乙個索引結構,葉節點data儲存了完整的資料記錄,這個索引的key是資料表的主鍵,因此innodb表資料檔案本身就是主索引。上圖是inno...
索引 資料結構
子元素比根元素大,放在右邊,反之亦然。如果資料從1開始遞增,依然使用二叉樹的話,二叉樹就會變成鍊錶結構 本質上是二叉樹,如果某一邊的子元素與另一邊的子元素相比超過二個,會發生自旋,一種平衡方式。也叫二叉平衡樹 在自增資料量很大的時候,樹的層數太高,查詢效率也會變低 葉節點具有相同的深度,葉節點的指標...
MySQL索引及索引資料結構
索引是幫助mysql高效獲取資料的排好序的資料結構 索引分類 索引失效的情況 模糊查詢時,第乙個查詢字元是不確定值 或 時,索引失效 select name from stu where name like e 索引失效 select name from stu where name like h ...