索引原理和優勢

lv99發表於2020-12-31

1.定義:

在關聯式資料庫中,索引是一種單獨的、物理的對資料庫表中一列或多列的值進行排序的一種儲存結構,它是某個表中一列或若干列值的集合和相應的指向表中物理標識這些值的資料頁的邏輯指標清單。索引的作用相當於圖書的目錄,可以根據目錄中的頁碼快速找到所需的內容。

2.原理: 

不同的資料庫,不同的儲存引擎其索引的原理也不盡相同。這裡只瞭解下MySQL的索引原理。不過,在瞭解索引之前我們需要先了解什麼是磁碟IO,區域性預讀,二叉樹。

   磁碟IO:很簡單,我們知道資料庫表裡的資料最終會持久化到磁碟裡面,當我們讀取資料的時候就需要從磁碟裡面讀取,每一次讀取就稱為一次磁碟IO。

   區域性預讀:也稱為區域性預讀原理,指的是當我們讀取一個資料的時候,該資料所在位置的相鄰資料也很快會被訪問到。

基於這兩個,我們就能瞭解下面的這句話;每一次讀取資料都會將其相鄰的資料也讀取出來,存放到資料庫記憶體快取中,這個資料塊稱為“頁”,也就是說,每一次磁碟IO讀取到一頁資料,頁的大小和作業系統有關,一般是4K或8K或16K。這也是我們經常聽到的,頁是其磁碟管理的最小單位。

二分法查詢二叉樹:二叉樹分為很多種,平衡二叉樹,完全二叉樹等,這裡的二叉樹是基於二分法查詢的,二分法簡單來講就是一串資料,提起中間的資料作為根節點將資料分為左右兩邊,左邊的資料再取中間的為節點提起來將其分為左右兩邊,右邊一樣,以此類推形成一棵倒著的樹,是為二叉樹。但這種樹要有一個要求就是資料必須是有序的,這也是我們一般要求聚集索引最好選用自增欄位的原因。如圖;

 

  1)MySQL:

       MySQL儲存引擎分為兩種:MyISAM和InnoDB。

     InnoDB:InnoDB儲存引擎一般分為以下幾種索引:B+樹索引,全文索引和雜湊索引。其中雜湊索引是自適應的,人為無法干預。B+樹索引就是我們一般通常所說的索引,B+樹索引的構造類似於二叉樹,注意,是類似,因為B+樹是從平衡二叉樹演化而來的,但B+樹不是一個二叉樹。這裡可能有人就不太明白了,要想明白這句話,首先得了解二分法和二叉樹。我們插入一段二叉樹得的解釋。

       二分查詢法:也稱折半查詢法,基本方法就是,將一組資料有序排列,採用跳躍方式查詢到這組資料中心點的位置,如果要找的資料小於中心點位置的資料,就在中心點左邊(也就是小於中心點資料的一邊)再次跳躍到這部分資料的中心位置比較,以此類推直到找到所要找的資料。這種方法的思路大概就是通過折半不斷縮小資料範圍。例如:

如有5、10、19、21、31、37、42、48、50、52這10個數,現要從這10個數中查詢48這條記錄,其查詢過程如圖所示。先找到這組資料中心位置37,判斷要找的48大於37就到37的右邊繼續二分定位到50,再判斷48小於50,直到找到48.

 

 

 二叉樹:

B+樹是通過二叉查詢樹,再由平衡二叉樹,B樹演化而來。二叉查詢樹是一種經典的資料結構,如圖:

 

 

 

圖中的數字代表每個結點的鍵值,在二叉查詢樹中,左子樹的鍵值總是小於根鍵值,右子樹的鍵值總是大於根鍵值。

當然,二叉樹可以任意構造,不一定非要求根節點一定是中心位置的鍵值,也可以這樣如下圖,它同樣滿足二叉樹的定義,右子樹鍵值大於根鍵值。但是顯然,這樣構造的二叉樹查詢的時候效率就很低了,為了最大效能的構造一棵二叉樹,平衡二叉樹(也稱AVL樹)應運而生!!

 

 

 

 

 平衡二叉樹:首先滿足查詢二叉樹,其次還需要滿足任何節點的兩個子樹的最大高度最大差為1,這樣一棵樹的效能是比較高的,但還不是最好的,最好效能的樹應該是最優二叉樹,但是世上哪得雙全法,最優二叉樹要求較高,需要大量的操作,因此,我們使用平衡二叉樹就足夠滿足我們了。

平衡二叉樹的查詢速度還是很快的,但是建立和維護一棵平衡二叉樹的代價也是很大的,通常需要1次或多次左旋和右旋來得到插入或更新後的樹的平衡,每一次資料的變化都意味著平衡二叉樹的變動。如圖,假如要插入一個值為9的節點,我們需要做的變動如下:

 

 這裡通過一次左旋就可以將樹維護到平衡狀態,但是有的情況要複雜一些,比如:

 

 

 

        可以看到,每次資料的增刪改都會引起二叉樹的變動,因此維護一顆平衡樹是需要開銷的,不過平衡二叉樹一般用於記憶體結構物件中,因此維護的開銷相對較小。

最後重點來了,B+樹!!!

B+樹:B+樹是由B樹和索引順序訪問法(ISAM:MySQL最初儲存引擎MyISAM的資料結構結構)演化而來。B+樹的定義在任何一本資料結構書中都能找到,其定義十分複雜,在這裡列出來只會讓讀者感到更加困惑。這裡,我來精簡地對B+樹做個介紹:B+樹是為磁碟或其他直接存取輔助裝置設計的一種平衡查詢樹。在B+樹中,所有記錄節點都是按鍵值的大小順序存放在同一層的葉子節點上,由各葉子節點指標進行連線。先來看一個B+樹,其高度為2,每頁可存放4條記錄,扇出(fan out)為5,如圖:

 

 

從圖可以看出,所有記錄都在葉子節點上,並且是順序存放的,如果使用者從最左邊的葉子節點開始順序遍歷,可以得到所有鍵值的順序排序:5、10、15、20、25、30、50、55、60、65、75、80、85、90。

 

B+樹索引:本質就是B+樹在資料庫中的實現,可分為集聚索引和非聚集索引,不管是哪種都是基於B+樹高度平衡的,葉子節點存放著所有資料,不同的是,聚索引存放的是一整行的資訊。

聚集索引:在InnoDB中,儲存引擎表就是索引組織表,即表中資料按照主鍵順序存放。而聚集索引就是按照每張表的主鍵構造的一棵B+樹,同時葉子節點存放著整張表得行記錄資料。也將聚集索引的葉子節點稱為資料頁。由於實際的資料頁只能按照一棵B+樹進行排序,因此每張表只能有一個聚集索引。可以這樣理解,找到索引就找到了資料。B+樹如下圖:

 

 

 有些文件會說聚集索引是按照順序物理地儲存資料,但這是不準確的。在《MySQL技術內幕》裡有介紹到,個人也比較認可這個:如果真的按照特定的物理順序存放,那麼維護成本相當之高,對於一些非自增主鍵的更新的處理代價非常大。聚集索引是邏輯上連續的,首先,資料頁是通過雙向連結串列進行維護的,頁按照主鍵的順序排序,並且每頁得記錄也是按照雙向連結串列維護的,物理儲存上也可以不按照主鍵儲存,如果已經按照物理順序排序了那麼雙向連結串列顯得多餘了。

非聚集索引:也叫輔助索引,葉子節點並不包含行記錄的全部資料,葉子節點除了包含鍵值外,還有一個書籤,這個書籤只是告訴你哪裡可以找到你要的資料,哪裡呢?聚集索引裡面去找吧。因此,整個輔助索引查詢過程是這樣的:先在輔助索引得B+樹上找到對應索引得書籤,在根據書籤資訊(對應的聚集索引樹的鍵值)去聚集索引的B+樹上找到對應的葉子節點資料。

    MyISAM:這是MySQL最早提供的引擎,也是B+樹。我們知道一般來講索引分為聚集索引和非聚集索引,在MyISAM中,這兩個原理差不多一樣,都是葉子節點存放地址資訊,即資料所在的行列資訊,再根據行列資訊找到資料。不同的是非聚集索引的鍵值允許重複。

稍微提一下SQL server索引,他的索引是基於B樹的。B樹設計之初的目的很簡單就是為了減少磁碟掃描的次數,也就是減少IO操作,避免全盤掃描。沒有聚集索引的表資料會以堆的結構無序存放。

B樹和B+樹的區別在於索引節點,B樹的索引節點裡面除了鍵值和指標為還有資料,但B+樹只有鍵值和指標,他的資料再葉子節點中,並且B+樹的葉子節點是一個雙向連結串列,查詢範圍非常快。那麼為什麼B+樹會比B樹好呢,除了上面提到的快速查詢外,還有一個原因是頁的容量大小是固定有限的,B+樹的索引節點頁不存放資料,可以容納更多的索引值。那麼相對應的B+樹的深度就會較淺,查詢更快。

相關文章