mysql聚簇索引詳解

聚簇索引

不是一種單獨的索引類型,而是一種數據存儲方式。innodb的聚簇索引實際上在同一個結構中保存了B-tree索引和數據行。

當表有聚簇索引時,數據行實際上是存儲在索引的葉子頁中。

聚簇:表示數據行和相鄰的鍵值緊湊地存儲在一起。一個表只能有一個聚簇索引

聚簇索引如何存放記錄如圖:

聚簇索引的優點:

    可以把相關數據保存在一起

    數據訪問更快(聚集索引將索引和數據保存在同一個b-tree中)

    使用覆蓋索引掃描的查詢可以直接使用頁節點中的主鍵值

聚簇索引的缺點:

    聚簇數據提高了IO性能,如果數據全部放在內存中,則訪問的順序就沒那麼重要了

    插入速度嚴重依賴插入順序。按主鍵的順序插入是速度最快的。但如果不是按照主鍵順序加載數據,則需在加載完成後最好使用optimize table重新組織一下表

    更新聚簇索引列的代價很高。因爲會強制innod將每個被更新的行移動到新的位置

    基於聚簇索引的表在插入新行,或主鍵被更新導致需要移動行的時候,可能面臨頁分裂的問題。頁分裂會導致表佔用更多的磁盤空間。

    聚簇索引可能導致全表掃描變慢,尤其是行比較稀疏,或由於頁分裂導致數據存儲不連續的時

    非聚集索引比想象的更大,因爲二級索引的葉子節點包含了引用行的主鍵列

    非聚集索引訪問需要兩次索引查找(非聚集索引中葉子節點保存的行指針指向的是行的主鍵值),對於innodb自適應哈希索引可以減少這樣的重複工作


innodb和myisam的數據分佈對比

myisam的數據分佈按照數據插入順序存儲在磁盤上,如圖:


主鍵分佈,如圖:


col2列索引分佈,如圖:


總結:myisam主鍵索引和其他索引在結構上沒有不同。主鍵索引就是一個名爲primary的非空唯一索引

innodb的數據分佈。存儲數據方式,如圖:

說明:聚簇索引的每個葉子節點都包含了鍵值、事務ID、用於事務和MVCC的回滾指針以及所有的剩餘列。如果主鍵是一個列前綴索引,innodb也會包含完整的主鍵列和剩下的其他列

使用主鍵值當作指針會讓非聚集索引佔用更多的空間,帶來的好處是:innodb在移動時無須更新非聚集索引中的這個‘指針’。

innodb非葉子節點包含了索引列和一個指向下級節點的指針(下一級可以是非葉子節點,也可以是葉子節點)

col2存儲數據方式,如圖:

innodb和myisam保存數據和索引的抽象圖:

在innodb表中按主鍵順序插入行

如果使用innodb表沒有什麼數據需要聚集,可以定義一個代理鍵作爲主鍵,使用auto_increment自增列。這樣可以保證數據行是按順序寫入,對於主鍵做關聯操作的性能也會更好

向聚簇索引插入順序的索引值,如圖:

說明:innodb把每一條記錄都存儲在上一條記錄的後面。當達到頁的最大填充因子(默認是頁大小的15/16,留下部分空間用於修改),下一條記錄會被寫入新的頁中

使用UUID插入聚簇索引的表,如圖:

說明:因爲新行的主鍵值不一定比之前插入的大,索引無法簡單的總是把新行插入到索引的最後,而是需要爲新的行尋找合適的位置——通常是已有數據的中間位置並分配空間。(會增加額外的工作,和數據分佈不夠優化)

缺點:

    1.寫入的目標頁可能已經刷到磁盤上並從緩衝中刪除,或還沒被加載到緩存中,innodb在插入之前不得不先找到然後從磁盤中讀取目標頁到內存中。會導致大量的隨機IO

    2.因爲寫入是亂序的,innodb不得不頻繁的做頁分裂操作,以便爲新的行分配空間。頁分裂會導致大量移動數據,一次插入需要修改多個頁(最少三頁)而不是一個頁

    3.由於頻繁的頁分裂,頁會變得稀疏並不被規則填充,所以數據會有碎片

順序主鍵在什麼時候會有更壞的結果:對於高併發工作負載,在innodb中按主鍵順序插入可能造成明顯的爭用。可能導致間隙鎖競爭和auto_increment鎖機制。


譯者介紹:家華,從事mysqlDBA的工作,記錄自己對mysql的一些總結

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章