這篇文章帶大家深入解析一下mysql中的索引,帶大家理解一下mysql索引原理,希望對大家有幫助!
索引是幫助MySQL高效取得資料的排好序的資料結構
前置知識:樹的高度越低查詢效率越高
資料結構模擬網址:https://www.cs.usfca.edu/~galles/visualization/Algorithms. html
(一)二元樹
問題:不能自平衡,極端情況出現傾斜,查詢效率和鍊錶類似
(二)紅黑樹
紅黑樹對資料進行平衡,解決了單邊增長的問題;
問題:資料量大的不適合,資料量大的時候,樹的高度不可控,從根節點到葉子節點,需要多次遍歷查找,效率偏低。
(三)Hash
1、對索引的key進行一次hash計算就可以定位出資料儲存的位置
2、很多時候Hash索引要比B 樹索引更有效率
3、只能滿足“=”,“IN”,不支援範圍查詢
4、hash衝突問題
(四)B-Tree
1、葉節點具有相同的深度,葉節點的指標為空;
2、所有索引元素不重複;
3、節點中的資料索引從左到右遞增排列;
(五)B Tree(B-Tree變種)
1、非葉子節點不儲存data,只儲存索引(冗餘),可以放更多的索引
2、葉子節點包含所有索引欄位
3、葉子節點用指標連接,提高區間存取的效能
這個問題的簡單答案是:約2千萬
在MySQL中我們的InnoDB頁的大小預設是16k,當然也可以透過參數設定:
SHOW GLOBAL STATUS LIKE "Innodb_page_size"
#資料表中的資料都是儲存在頁中的,所以一個頁中能儲存多少行資料呢?假設一行資料的大小是1k,那麼一個頁可以存放16行這樣的資料。
如果資料庫只以這樣的方式存儲,那麼如何查找資料就成為一個問題
因為我們不知道要查找的資料存在哪個頁中,也不可能把所有的頁遍歷一遍,那樣太慢了。
所以人們想了一個辦法,用B 樹的方式來組織這些資料。如圖所示:
InnoDB中主鍵索引B 樹是如何組織資料、查詢資料的,我們總結一下:
1、InnoDB儲存引擎的最小儲存單元是頁,頁可以用於存放數據也可以用於存放鍵值指針,在B 樹中葉子節點存放數據,非葉子節點存放鍵值指針。
2、索引組織表透過非葉子節點的二分查找法以及指標確定資料在哪個頁中,進而在去資料頁中查找到需要的資料;
那麼回到我們開始的問題,通常一棵B 樹可以存放多少行資料?
這裡我們先假設B 樹高為2,即存在一個根節點和若干個葉子節點,那麼這棵B 樹的存放總記錄數為:根節點指標數*單一葉子節點記錄行數。
上文我們已經說明單一葉子節點(頁)中的記錄數=16K/1K=16。 (這裡假設一行記錄的資料大小為1k,實際上現在很多網路業務資料記錄大小通常是1K左右)。
那麼現在我們需要計算非葉子節點能存放多少指標?
其實這也很好算,我們假設主鍵ID為bigint型,長度為8字節,而指標大小在InnoDB源碼中設定為6字節,這樣共14字節
#我們一個頁中能存放多少這樣的單元,其實就代表有多少指針,即16384/14=1170。
那麼可以算出一棵高度為2的B 樹,能存放1170*16=18720個這樣的資料記錄。
根據同樣的原理我們可以算出一個高度為3的B 樹可以存放:1170* 1170 *16=21902400條這樣的記錄。
所以在InnoDB中B 樹高度一般為1-3層,它就能滿足千萬級的資料儲存。
在尋找資料時一次頁的查找代表一次IO,所以透過主鍵索引查詢通常只需要1-3次IO操作即可查找到資料。
B樹
葉子節點具有相同的深度,葉子節點的指標為空
所有索引元素不重複
節點中的資料索引從左到右遞增排列
B 樹索引
非葉子節點不儲存data,只儲存索引(冗餘),可以放更多的索引
葉子節點包含所有索引字段
葉子節點用指標連接,提高區間存取的效能
為什麼data節點挪到葉子節點,一個節點可以儲存更多的索引
16^n=2000萬,n就是樹的高度,儲存同樣的數據,B 樹的高度遠小於B樹
因為B樹不管葉子節點還是非葉子節點,都會保存數據,這樣導致在非葉子節點中能保存的指針數量變少(有些資料也稱為扇出)
指標少的情況下要保存大量數據,只能增加樹的高度,導致IO操作變多,查詢效能變低;
聚集索引的意思:葉子節點存放了索引和資料又叫叢集索引。
非聚集索引又叫稀疏索引。主鍵索引就是一種聚集索引!
(一)MyISAM索引檔案和資料檔案是分離的(非聚集)
MyISAM索引檔案和資料檔案是分離的(非聚集),儲存引擎是作用於表格中的;
索引檔案存放索引,資料檔案存放數據,索引和資料不放在一起存
查詢:先查詢B 樹上的索引,再用查詢到的位置查詢資料檔案
(一)InnoDB索引實作
表資料索引資料存放在.ibd檔中
1、表資料檔本身就是按B Tree組織的一個索引結構檔
2、聚集索引-葉節點包含了完整的資料記錄
(1)主鍵索引:
(2)輔助索引(二級索引)
主鍵索引的葉子節點儲存了完整的資料行,而非主鍵索引的葉子節點儲存的則是主鍵索引值,透過非主鍵索引查詢資料時,會先查找到主鍵索引,然後再到主鍵索引上去找出對應的數據,這個過程叫做回表(下文中會再次提到)。
二級索引與叢集索引有幾處不同:
#(3)聯合索引:
以多個欄位的大小為排序規則建立的B 樹稱為聯合索引,本質上也是一個二級索引。
3、為什麼建議InnoDB表必須建立主鍵,並且推薦使用整數的自增主鍵?
(1)主鍵是InnoDB用來建構B 樹的。如果沒有主鍵,會使用唯一的列作為索引,如果還是沒有,會建立隱藏列,作為索引列。
(2)如果不用整型的自增主鍵,用UUID當主鍵會怎麼樣?
UUID是字串類型,查詢操作會有比較操作,整型比較操作快,整數主鍵比UUID省空間,UUID不是自增的
(3)HASH索引:值做hash運算,運算後的值和儲存位置一一映射
為什麼不用Hash?
Hash對範圍查詢支援不好。某一列資料是無序的,B 樹在建構的時候可以讓資料有序。
4、為什麼非主鍵索引結構葉節點儲存的是主鍵值? (一致性與節省儲存空間)
1、每個索引都對應一棵B 樹。使用者記錄都儲存在B 樹的葉子節點,所有目錄記錄都儲存在非葉子節點。
2、InnoDB儲存引擎會自動為主鍵(如果沒有它會自動幫我們新增)建立叢集索引,叢集索引的葉子節點包含完整的使用者記錄。
3、可以為指定的列建立二級索引,二級索引的葉子節點包含的使用者記錄由索引列主鍵組成,所以如果想透過二級索引來查找完整的使用者記錄的話,需要透過回表操作,也就是在透過二級索引找到主鍵值之後再到聚集索引中尋找完整的使用者記錄。
4、B 樹中每層節點都是依照索引列值從小到大的順序排序而組成了雙向鍊錶,而且每個頁內的記錄(不論是使用者記錄還是目錄項記錄)都是依照索引列的值從小到大的順序而形成了一個單鍊錶。如果是聯合索引的話,則頁面和記錄先按照聯合索引前邊的列排序,如果該列值相同,再按照聯合索引後邊的列排序。
透過索引來尋找記錄是從B 樹的根節點開始,一層一層會向下搜尋。由於每個頁面都按照索引列的值建立了頁目錄,所以在這些頁面中的查找非常快。
查看部落格:Mysql索引會失效的幾個情況總結
https://blog. csdn.net/weixin_36586564/article/details/79641748
【相關推薦:mysql影片教學】
以上是深入解析mysql中的索引(原理詳解)的詳細內容。更多資訊請關注PHP中文網其他相關文章!