MySQL優化(三) 索引原理及索引優化

2021-08-19 22:22:42 字數 2641 閱讀 9497

b-tree索引,它是目前關係型資料庫中查詢資料最為常用和有效的索引,大多數儲存引擎都支援這種索引。使用b-tree這個術語,是因為mysql在create table或其它語句中使用了這個關鍵字,但實際上不同的儲存引擎可能使用不同的資料結構,比如innodb就是使用的b+tree

中的b是指balance,意為平衡。需要注意的是,b+樹索引並不能找到乙個給定鍵值的具體行,它找到的只是被查詢資料行所在的頁,接著資料庫會把頁讀入到記憶體,再在記憶體中進行查詢,最後得到要查詢的資料。

b+tree前,先了解一下二叉查詢樹,它是一種經典的資料結構,其左子樹的值總是小於根的值,右子樹的值總是大於根的值,如下圖①。如果要在這課樹中查詢值為5的記錄,其大致流程:先找到根,其值為6,大於5,所以查詢左子樹,找到3,而5大於3,接著找3的右子樹,總共找了3次。同樣的方法,如果查詢值為8的記錄,也需要查詢3次。所以二叉查詢樹的平均查詢次數為(3 + 3 + 3 + 2 + 2 + 1) / 6 = 2.3次,而順序查詢的話,查詢值為2的記錄,僅需要1次,但查詢值為8的記錄則需要6次,所以順序查詢的平均查詢次數為:(1 + 2 + 3 + 4 + 5 + 6) / 6 = 3.3次,因此大多數情況下二叉查詢樹的平均查詢速度比順序查詢要快。

)操作就將插入後的樹重新變為平衡二叉樹是最簡單的情況了,實際應用場景中可能需要旋轉多次。至此我們可以考慮乙個問題,平衡二叉樹的查詢效率還不錯,實現也非常簡單,相應的維護成本還能接受,為什麼mysql索引不直接使用平衡二叉樹?

b+tree就是一種多路搜尋樹。理解b+tree時,只需要理解其最重要的兩個特徵即可:第一,所有的關鍵字(可以理解為資料)都儲存在葉子節點(leaf page),非葉子節點(index page)並不儲存真正的資料,所有記錄節點都是按鍵值大小順序存放在同一層葉子節點上。其次,所有的葉子節點由指標連線。如下圖為高度為2的簡化了的b+tree

b+tree作為索引儲存結構的重要原因。

b+tree的高度為h,一次檢索最多需要h-1次i/o(根節點常駐記憶體),複雜度o(h) = o(logmn)。實際應用場景中,m通常較大,常常超過100,因此樹的高度一般都比較小,通常不超過3。

b+tree節點的操作,在整體上對索引的維護有乙個大概的了解,雖然索引可以大大提高查詢效率,但維護索引仍要花費很大的代價,因此合理的建立索引也就尤為重要。

為了保持平衡,對於新插入的值需要做大量的拆分頁操作,而頁的拆分需要i/o操作,為了盡可能的減少頁的拆分操作,b+tree也提供了類似於平衡二叉樹的旋轉功能。當leaf page已滿但其左右兄弟節點沒有滿的情況下,b+tree並不急於去做拆分操作,而是將記錄移到當前所在頁的兄弟節點上。通常情況下,左兄弟會被先檢查用來做旋轉操作。就比如上面第二個示例,當插入70的時候,並不會去做頁拆分,而是左旋操作。

b+tree的資料結構已經有了大致的了解,但mysql中索引是如何組織資料的儲存呢?以乙個簡單的示例來說明,假如有如下資料表:

當出現多個索引做聯合操作時(多個or條件),對結果集的合併、排序等操作需要耗費大量的cpu和記憶體資源,特別是當其中的某些索引的選擇性不高,需要返回合併大量資料時,查詢成本更高。所以這種情況下還不如走全表掃瞄。

explain時如果發現有索引合併(extra欄位出現using union),應該好好檢查一下查詢和表結構是不是已經是最優的,如果查詢和表都沒有問題,那只能說明索引建的非常糟糕,應當慎重考慮索引是否合適,有可能乙個包含所有相關列的多列索引更適合。

(staff_id,customer_id)的索引還是應該顛倒一下順序?執行下面的查詢,哪個欄位的選擇性更接近1就把哪個字段索引前面就好。

(user_group_id,trade_amount),如果不考慮特殊情況,這看起來沒有任何問題,但實際情況是這張表的大多數資料都是從老系統中遷移過來的,由於新老系統的資料不相容,所以就給老系統遷移過來的資料賦予了乙個預設的使用者組。這種情況下,通過索引掃瞄的行數跟全表掃瞄基本沒什麼區別,索引也就起不到任何作用。

索引是有按照列值順序儲存的,對於i/o密集型的範圍查詢要比隨機從磁碟讀取每一行資料的io要少的多

type列的值為index表示使用了索引掃瞄來做排序。

order by子句的順序完全一致,並且所有列的排序方向也一樣時,才能夠使用索引來對結果做排序。如果查詢需要關聯多張表,則只有order by子句引用的字段全部為第一張表時,才能使用索引做排序。order by子句和查詢的限制是一樣的,都要滿足最左字首的要求(有一種情況例外,就是最左的列被指定為常數,下面是乙個簡單的示例),其他情況下都需要執行排序操作,而無法利用索引排序。

(a,b),再建立索引(a)就是冗餘索引。冗餘索引經常發生在為表新增新索引時,比如有人新建了索引(a,b),但這個索引不是擴充套件已有的索引(a)

MySQL索引原理及查詢優化

其實在工作中有去優化mysql語句,但之前優化僅僅是降到能夠接受花費時間之下,並有很多可以繼續提供的空間。很多時候在優化完成之後sql,也並不能向外展示。故這裡將自己平時優化的sql方法記錄下來,並找到乙個總結優化sql的地方。索引原理 mysql的建立索引其實就像是字典的目錄有一定的相似之處,通過...

索引優化及原理

oracle 之sql優化 索引的基本原理 一 1 索引的基本概念 1 建立索引的目的 以索引小的io換取表的大io。何時建立索引 當訪問的資料塊少於表中20 的資料時,建議使用索引。2 索引的 會使insert delete速度變慢 索引個數多的話速度就會慢 對於update語句,需要先判斷是否要...

MySQL索引原理及慢查詢優化

通過不斷的縮小想要獲得資料的範圍來篩選出最終想要的結果,同時把隨機的事件變成順序的事件,也就是我們總是通過同一種查詢方式來鎖定資料。資料庫索引就是通過演算法提高查詢效率。磁碟io與預讀 考慮到磁碟io是非常高昂的操作,計算機作業系統做了一些優化,當一次io時,不光把當前磁碟位址的資料,而是把相鄰的資...