MySQL優化之索引原理(二)


一,前言

​ 上一篇內容說到了MySQL存儲引擎的相關內容,及數據類型的選擇優化。下面再來說說索引的內容,包括對B-Tree和B+Tree兩者的區別。

1.1,什么是索引

​ 索引是存儲引擎用於快速找到記錄的一種數據結構, 對性能的提升有很大的幫助,尤其當表中數量較大的情況下,索引正確的使用可以對性能提升幾個數量級。
但是索引經常被忽略,不恰當的索引對性能可能還會帶來負面效果。

1.2,什么時候添加索引

  • 主鍵自動建立主鍵索引(唯一索引)

  • where字句中的列,頻繁作為查詢字段的列

  • 表連接關聯的列

  • 排序用到的列

  • 索引的基數越大(選擇性大),索引的效率就越高

    什么叫基數越大,比如手機號,每個列都具有不同的值,非常好區別,這個就適合建立索引,而性別這樣的字段,因為只有兩個值,以不適合建立索引,就是區分度高低的問題。

1.3,不適合添加索引

  • 表中數據太少
  • 頻繁修改的字段
  • 數據重復且分布平均的字段

1.4,索引的分類

單值索引:即一個索引只包含單個列,一個表可以有多個單列索引。

唯一索引:索引列的值必須唯一,但是允許有空值。

復合索引:即一個索引包含多個列。

全文索引:使用fulltext創建全文索引。

在舊版MySQL中全文索引只能用在MyISAM表格的char、varchar和text的字段上。新版的MySQL5.6.24上InnoDB引擎也加入了全文索引。

​ 使用方式:

  • 創建索引:create [unique|fulltext] index 索引名 on 表名 (屬性名[長度][asc|desc])。
  • 刪除索引:drop index 索引名 on 表名。
  • 查看索引:show index from 表名。

具體使用方式這里就不詳細說明,接下來就說說關於索引的實現原理,Tree,B-Tree,B+Tree。

二,Tree

​ 在總結B-Tree和B+Tree之前,先看看最基本的二叉樹結構吧,因為前兩種樹結構夠可以算是二叉樹的變種。

​ 二叉樹是n(n>=0)個結點的有限集合,該集合或者為空集(稱為空二叉樹),或者由一個根結點和兩棵互不相交的、分別稱為根結點的左子樹和右子樹組成。

二叉樹的特點:

  • 每個結點最多有兩顆子樹,所以二叉樹中不存在度大於2的結點。
  • 左子樹和右子樹是有順序的,次序不能任意顛倒。
  • 從根節點出發,左子樹都是比根節點小的,而右子樹都是比根節點大的。

​ 因此對於較平衡的二叉樹的查找性能,是幾乎接近於二分查找的,但是如果存入的數據都比根節點小,或者都比根節點大,則會出現以下情況。

​ 這兩種情況分別是左斜樹和右斜樹,上述情況毫無疑問在二叉樹搜索時,效率是非常低的。因為它已經失去了樹的結構,不管是查詢節點,還是添加刪除等,都是對每個節點依次遍歷,直到查出目標節點為止。

​ 另外還有一點也是很重要,如果二叉樹的字節點或多,一百萬,一千萬,甚至上億數據。對於較大數據量的二叉樹,會將其保存在磁盤中,那么問題來了。如果要查詢的數據在樹的底層,那么就勢必會造成多次的磁盤IO,而磁盤IO的讀取比內存讀取的速度要低100倍左右。這種情況下,不管是從性能來說,還是效率這都不是一個好的結果。

​ 接着再說B-Tree結構,是二叉樹的一種升級版。

三,B-Tree

​ B樹又被成為平衡多路查找樹。

  • 樹中每個結點最多含有m個節點(且m>2)。
  • 除根結點和葉子結點外,其它每個結點至少有[m / 2,m]個孩子。
  • 若根結點不是葉子結點,則至少有2個孩子(特殊情況:整棵樹只有一個根節點)。
  • 所有葉子結點都出現在同一層。

​ 在B-Tree或者B+Tree中,都會存在一個關於的概念,也就是上面提到的m值。什么是度,可以說是我們自定義的一個閾值,當節點數量達到這個閾值時,樹的結構便會發生變化,此時便轉變成B-Tree結構。

​ 現在,設定度(m)為3,首先我們先插入兩個節點:

​ 發現在B樹結構中,當插入9節點時,並沒有成為8節點的右子樹,這是為什么。首先在於這就是B樹的結構特點,沒有成為8節點的右子樹是不是就減少了樹的層級深度。其次就是我們設定B樹的度為3,接着將再添加10節點,看有什么變化。

​ 這個時候已經達到最大值3,那么根據二叉樹的結構特點,將9提升為根節點,8和10分別為9的左右子節點。

繼續添加6

添加11

添加15

分析:

​ 1,當添加11完成時,葉子節點全部都達到了度為2,而添加15時,由於比根節點9大,所以添加到右子樹中。則右子樹變成001000110015。顯然達到我們設定的閾值,根據以上規則,將0011提升為根節點。

​ 2,從圖中可以看出,9的左邊都是比根節點小,9到11之間都是大於9小於11的,最后11的右邊都是大於11的。

​ 3,最后我們再添加5,我們先來分析下結構會如何變化,5小於9,所以會在左邊,變成005006008,這個時候節點數量變成3,根據規則006應該提升為根節點。但是根節點又會變成0060090011,同樣達到閾值,那么將009再提升為根節點。最終結果如圖:

​ 以上就是B-Tree的原理總結,那么這與二叉樹有什么區別呢。最直觀的就是樹的層級變少了,同樣也不會出現左右斜樹的情況。

在InnoDB存儲引擎中有頁(Page)的概念,頁就是磁盤管理的最小單位。InnoDB存儲引擎中默認每個頁的大小為16KB。並且可通過參數innodb_page_size將頁的大小設置為4K、8K、16K。

​ 在B-Tree中,每個節點都會攜帶一個key信息,用於保存該數據在表中的位置,同時也會將數據保存到節點中。當節點不是葉子節點時,父節點會攜帶對象的指針指向其子節點在磁盤中的位置。根據磁盤存儲的頁大小,如果每個葉子節點都攜帶較多的信息,那么在磁盤中占用的空間資源也會越多。顯然這不是一個好的現象,因此就出現B-Tree的優化版,B+Tree。

四,B+Tree

​ InnoDB存儲引擎就是用B+Tree實現其索引結構。

​ 在B+Tree結構中,每一層非葉子節點只存儲key值信息,而葉子節點只存放數據信息。這種結構不僅節省磁盤的空間,對節點的查詢效率也大大提高了很多。

​ 除此之外,非葉子節點的key最終會全部出現在葉子節點上, 這么說很抽象,請看演示效果。

​ 首先添加7,8兩個節點。

​ 接着添加9節點。

​ 同樣度達到了3,將8提升為根節點。但是與B-Tree不同的是,在葉子節點中也存在8節點,這就是B+Tree結構的特點,然后再添加10節點。

​ 以此類推,在最后的葉子節點中,整個樹中的key都在存在,那么這與B-Tree有什么區別呢。每個節點中沒有數據存儲,只有key值信息,在磁盤中會存儲更多的數據。

五,總結

​ 思考一個問題:

​ 對於查詢效率最快的數據結構,哈希表的效率要比樹狀結構快的多,那么MySQL存儲引擎為什么不采用哈希表結構存儲數據,原因就是哈希表是不能進行范圍查找。

​ 本篇博客並沒有講述對索引使用的優化,只系統闡述了MySQL索引的底層機制,那么使用索引優化,查詢優化,庫表結構優化會在最后一篇博客中全部分享完。

​ 以上內容均是自主學習總結,如有錯誤歡迎留言指正。

感謝閱讀!


免責聲明!

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



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