資料庫——對索引的理解

it_was發表於2020-09-26

索引是一種用於資料庫高效獲取資料資料結構:facepunch:
:arrow_right:以下討論主要基於InnoDB儲存引擎!

首先需要注意的是InnoDB儲存引擎表就是索引組織表!即在InnoDB中資料即索引,索引即資料。而這個儲存引擎表(索引表)中的資料是按照主鍵順序排列。將聚集索引的葉子節點稱為資料頁

主要有兩種資料結構——雜湊索引和B樹索引(尤以B+樹為主:boom:

  • 雜湊索引:不必多說,雜湊索引即根據雜湊演算法將目標欄位的key轉為陣列的下標,進而一步定位到目標資料進而獲得值。

    InnoDB引擎支援雜湊索引是自適應的,會根據表的使用情況自動為表生成雜湊索引,而不能人為干預是否生成雜湊索引!言外之意,InnoDB不能顯示的建立雜湊索引,下圖可知
    資料庫——對索引的理解

  • B+樹索引是現在主流資料庫系統中最經常用到和最為有效的索引,其結構類似二叉樹,又高於二叉樹:boom:

    B+樹中的B代表的是Balance,即平衡之意,由最早的平衡二叉樹(AVL)演化而來!

  • 全文索引
    雖然在資料庫總使用 like + % 就可以實現大部分的模糊查詢,但這種情況終究還是受限於資料量,當資料量大的時候效率是極其低下的!所以全文索引就應運而生.
    全文索引通常使用倒排索引來實現。即單詞 ——> 位置的形式

    通過數值比較、範圍過濾等就可以完成絕大多數我們需要的查詢,但是,如果希望通過關鍵字的匹配來進行查詢過濾,那麼就需要基於相似度的查詢,而不是原來的精確數值比較。全文索引就是為這種場景設計的。

B+樹索引和雜湊索引的區別::boom:

  • 等值查詢,雜湊索引明顯有絕對優勢
  • 雜湊索引不支援範圍查詢,而B+樹支援
  • B+樹可以很好地應對排序等查詢
  • 在有大量重複鍵值情況下,由於雜湊碰撞其效率也是極低的

4.1 B樹 :raising_hand:

我們可以先來看下B樹:eyes:

因為記憶體的易失性。一般情況下,我們都會選擇將資料庫表中的資料和索引儲存在磁碟這種外圍裝置中。但是和記憶體相比,從磁碟中讀取資料的速度會慢上百倍千倍甚至萬倍,所以,我們應當儘量減少從磁碟中讀取資料的次數。
另外,從磁碟中讀取資料時,都是按照磁碟塊來讀取的,並不是一條一條的讀。
如果我們能把儘量多的資料放進磁碟塊中,那一次磁碟讀取操作就會讀取更多資料,那我們查詢資料的時間也會大幅度降低。
平衡二叉樹是每個節點只儲存一個鍵值和資料的。那說明什麼?說明每個磁碟塊僅僅儲存一個鍵值和資料!那如果我們要儲存海量的資料呢?
可以想象到二叉樹的節點將會非常多!高度也會極其高!我們查詢資料時也會進行很多次磁碟 IO,我們查詢資料的效率將會極低!

總結來收,就是因為不論什麼樣的二叉樹,在海量資料面前,整個樹的結構變得極其瘦高!查詢效率非常低下,因為需要多次訪問磁碟資料塊(頁),代價昂貴。因此就引出以下B樹這種結構:clap:

節點稱為頁,頁就是我們上面說的磁碟塊,在 MySQL 中資料讀取的基本單位都是頁,所以我們這裡叫做頁更符合 MySQL 中索引的底層資料結構。

資料庫——對索引的理解
B 樹相對於平衡二叉樹,每個節點儲存了更多的鍵值(key)和資料(data),並且每個節點擁有更多的子節點,子節點的個數一般稱為階,上述圖中的 B 樹為 3 階 B 樹,高度也會很低。這樣一來,資料的查詢效率就比一般的二叉樹高!:smiley:

4.2 B+樹

簡單來講,B+樹是為磁碟或其他直接存取輔助裝置設計的一種平衡查詢樹。在B+樹種,所有記錄節點都是按照鍵值的大小順序存放在同一層葉子節點上的,由各葉子節點雙向指標進行連線!

資料庫——對索引的理解

4.3 B樹和B+樹的對比

  • B 樹節點中不僅儲存鍵值,也會儲存資料;而 B+ 樹非葉子節點上是不儲存資料的,僅儲存鍵值

    之所以這麼做是因為在資料庫中頁的大小是固定的,InnoDB 中頁的預設大小是 16KB。如果不儲存資料,那麼就會儲存更多的鍵值,相應的樹的階數(節點的子節點樹)就會更大,樹就會更矮更胖,如此一來我們查詢資料進行磁碟的 IO 次數又會再次減少,資料查詢的效率也會更快。
    :collision: 即 B+ 樹擁有高扇出性!
    B+ 樹的階數是等於結點鍵值最多的數量

  • B+ 樹索引的所有資料均儲存在葉子節點,而且結點之間有雙向連結串列,結點內部也是雙向連結串列,高效的支援範圍查詢和排序查詢!

:shipit:上圖中的 B+ 樹索引就是 InnoDB 中 B+ 樹索引真正的實現方式,準確的說應該是聚集索引
MyISAM 中的 B+ 樹索引實現與 InnoDB 中的略有不同。在 MyISAM 中,B+ 樹索引的葉子節點並不儲存資料,而是儲存資料的檔案地址。即非聚集索引


:question:延申一 : 扇入和扇出

  • 扇入:是指直接呼叫該模組的級模組的個數。扇入大表示模組的複用程式高。
  • 扇出:是指該模組直接呼叫的下級模組的個數。扇出大表示模組的複雜度高,需要控制和協調過多的下級模組;但扇出過小(例如總是1)也不好。

:hear_no_evil: 如果你看到這了就不妨繼續往下看吧!

4.4 B+樹索引之聚集索引和非聚集索引

剛剛我們介紹完了B+樹索引的資料結構,也知道了InnoDB儲存引擎採用的是B+樹索引,並且葉子節點存放的是鍵值和和資料,即聚集索引!那麼聚集索引和非聚集索引到底是什麼呢?

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章