mysql 松散索引與緊湊索引掃描(引入數據結構)


    這一篇文章本來應該是放在 mysql 高性能日記中的,並且其優化程度並不高,但考慮到其特殊性和原理(索引結構也在這里稍微講一下)

一,mysql 索引結構 (B、B+樹)

    要問到 mysql 的索引用到什么數據結構,我相信大部分都能回答出來,沒錯,就是 B+ 樹。那再問為什么要用 B+ 樹呢,與紅黑樹,hash 表又分別有什么區別呢,問到這里可能就難住了一些沒思考過的輕度玩家了。這里簡單描述一下

    B 樹與紅黑樹的區別,有數據結構基礎的同學應該可以講出來,紅黑樹是平衡二叉樹的一個變種,利用紅黑樹的 5 個特征保證其近乎平衡,記住,紅黑樹降低的左轉右轉的遞歸向上,但其並不是絕對平衡,但非極端情況下,我們也可以說紅黑樹的查詢和插入都是 log2n 的時間復雜度;而 B 樹可以理解為平衡 n 插樹,每個數的節點並不是一個值,而是一個數組,每兩個數值之間指向一個在兩者之間范圍的新節點,這里可以看到對於相同的數據量,B 樹的高度遠遠小於,根據官方給出一般索引的高度不會超過 5 的高度計算,3億的數據量僅需要每個節點 50 個數據,mysql 在每個節點的遍歷也是用最快的二分查找,所以查詢一個 3億 數據量的時間復雜度僅為 5log250,算下來幾乎為常數級

 

    B 樹與 hash 表的區別,hash 的查詢會比 B 樹更快一些,好的 hash 表甚至可以達到 1-5 次查詢得到結果,但與已經是常數級的 B 樹相比,並沒有太大的一個優化,但 hash 的插入卻很容易產生 hash 沖突,現有解決 hash 沖突的方法無不是需要耗費大量時間進行重新 hash,相較微量的查詢優化,寫的效率過低導致 mysql 不可能使用 hash 表作為索引結構。

    mysql 的索引結構其實本質是 B 樹的一個變種結構 -- B+ 樹,相較 B 樹,B+ 樹更適用於文件型索引,其每個非葉子節點存儲的只是用於索引排序的輔助數值,而真正的數據都放在葉子節點,對於 mysql 這種不僅僅存單純的排序值,而是關系型數據的 db,當然是 B+ 樹更適合作為索引結構,當然還有一個小的優化點是子節點之間是有指針連接的,加快了范圍查找的速度。

 

 

 

 二,復合索引結構

     對於主鍵索引,肯定索引結構是按一個主鍵的順序組合的 B 樹,但對於一個含有兩個列的復合索引,它的樹狀結構是什么樣呢?

     對於復合索引 Index(A,B),B 樹的排序是按 A 列的數值為第一要素,B 列的數值為第二要素進行排序,這也就是為什么我們查詢語句時,條件語句必須保證最左原則才可以利用到索引

     這里引入一些題外話,聚簇索引(Innodb)和非聚簇索引(myisam),因為講到索引結構,這里引入這個話題,也是 mysql 中比較常用的兩大引擎的一個區別,聚簇索引的索引的葉節點存放的直接是數據的葉節點,當使用輔助(符合)索引查詢時,其葉子節點存放的是主鍵的值,所以通過符合索引查找非覆蓋索引數據時,都會進行兩次查詢,並且查詢主鍵的速度沒有 myisam 的速度快;非聚簇索引指索引的葉節點存放的是數據的頁數據指針,輔助索引存的同樣是指針。兩者各有千秋,不能說哪個好哪個壞,按業務自身選擇即可

    回到正題,那對於復合索引的查詢是如何的過程,那如果真的想要只查 B 又想用到索引,該如何使用呢?引入我們的第三個話題

,緊湊索引與松散索引

     如果不遵守最左原則,where b = xxx,就會使用緊湊索引遍歷的方式,進行全表掃表。而我們如果真的有些情況,需要查出符合 B 條件但對 A 不進行限制的情況,應該如何處理,可能有些同學會新開一個獨立索引僅包含 B 列,這樣雖然能達到我們的目的,但難免有些多余。mysql 也是也能很好的進行跳躍松散索引掃描,只是 mysql 優化器無法自動進行,必須在查詢語句中進行必要的聲明。 select * from xxx where B = xxx group by A; 添加 group by 字段后,會先根據 A 索引分組后,會在每個 A 的范圍內使用索引進行快速查詢定位所需要的 B 列,這就叫做松散索引掃描,比新建一個索引的效率會慢 A 的 distinct 倍,但省去了新索引的消耗。

 

 

 

 

 --業務程序員

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM