(重點)MySQL(入門篇25)MySQL BTree索引背後的數據結構及算法原理

目錄

BTree俗稱B樹,MySQL數據庫支持多種索引,但是我們平時主要使用B樹索引,所以本文重點介紹B樹索引,這是文章目錄

一、MySQL數據庫索引的原理(數據結構及算法層面)
二、B樹(B-treee)和B+樹(B + tree) 的區別和聯繫
二、聚集索引和非聚集索引的區別(結合InnoDB和myISAM)
三、如何正確且高性能地使用索引?

一、數據庫索引的原理

1. 索引的本質

數據結構(一種高效獲取的數據的數據結構)

2.索引的背景

數據庫的主要功能之一i就是數據庫查找,如何能查找的更快就是關鍵,最基本的查找算法就是順序查找(挨個遍歷,等於就取出),但是當數據量十分大的時候比如說10億,挨個遍歷就會變得十分緩慢,這時候產生了許多優秀的算法,二分查找(就像猜數字數據結構要有序)和二叉樹查找數據結構爲二叉樹),對數據結構由要求,但是很多數據數據不能滿足數據結構比如說文章,或者圖片,這個時候索引就出現了,索引用某種方式引用(指針指向)數據,,索引這種數據結構適合實現高級的查找算法。(例如3.索引的使用例子)

3.索引的使用例子

在這裏插入圖片描述
左邊是一個表的實例,和地址,右邊是**二叉查找數據結構的索引,**時間複雜度O(log2n),十分的快速。

二、 B - tree 和 B + tree的 區別和聯繫?

  • 大部分數據庫都採用 B-tree 或者 B+Tree的數據結構,
  • 爲什麼應用如此廣泛?
  • 效率高,速度快
  • 爲什麼速度快?
  • 根據磁盤IO讀取的原理,和B樹的數據結構
  • 爲什麼不用二叉樹呢?
    考慮到磁盤IO的原理,磁盤IO相對於內存是很慢的(移動磁針…)當數據量很大的時候,就不能全部索引都讀取到內存上,只能每一個頁的加載(對應索引樹的節點)爲了減少IO的次數**(IO的次數就是B數的高度h)**,h儘量小,所以不用二叉樹。

1 B樹(Balance-Tree)

1.1 b樹的特徵
  1. 非葉子節點只能有M個兒子,M > 2
  2. 根節點的兒子數量爲 [2,M]
  3. 根節點以外的非葉子節點的兒子數量爲[M/2,M]
  4. 非葉子節點的關鍵字的個數 = 兒子數量 - 1
  5. 所有葉子節點位於同一層
  6. k個關鍵子,把節點拆分爲 k + 1段,指向 K +1個兒子,滿足查找樹的大小的關係
1.2 特性(注意區分後面的 B + 樹)
  • 1.關鍵字集合分佈在整個樹上,(B+樹在最下端的葉子上
  • 2 一個關鍵字字出現在一個節點上,(B+樹非葉子的節點上的關鍵字會重複)
  • 3.搜索肯能在非葉子節點,也有肯在葉子節點結束(B+樹只能在底部的葉子節點結束)
  • 4.搜索性能等價於在關鍵字全集內做一個二分查找(B+樹…)
1.3 (重點)例子1, 查詢元素5

(1)找根節點 9 所在數據讀取到內存 然後比較 比較 5 < 9 所以,數據在 B樹的左邊,下次查詢左邊

在這裏插入圖片描述
(2)找到左邊 2 6 所在的節點 數據讀取到內存,比較 2<5<6 ,所以下一次查找中間的數據
在這裏插入圖片描述
(3)再次找到中間的數據讀取到內存,比較得到答案。5的位置讀取 5 指向的地址(指針),就讀取到了對應的數據.
在這裏插入圖片描述

1.4 (重點)例子2, 插入元素 4

(1)和例子1的方式一樣連續查找和比較,找到4對應點位置在 3 - 5 之間。
在這裏插入圖片描述
(2)但是並不能插進入,三階樹的每個節點最多有 (3-1) = 2 個元素,所以只能將 4 上移到 2 和 6 之間。再次判斷是否能插入…(上移是關鍵操作!)
在這裏插入圖片描述
(3)再次判斷,最多隻能有 (3-1) = 2 個,單個節點元素過多,再次上移
在這裏插入圖片描述
(4)此時滿足條件,就插入到根節點,此時根節點元素爲 4 , 9
在這裏插入圖片描述
(5)爲了滿足樹的結構,再次對樹進行調整,得到最終結果如下。
在這裏插入圖片描述

1.5 (重點)例子3,刪除元素 11

(1)使用例子1的方法查詢到 11 的位置刪除它
在這裏插入圖片描述
(2)12 的節點只有一個兒子,不符合樹結構了,所以左旋,12下來,13上去 最終結果如圖。
在這裏插入圖片描述
(3)拓展:如果要再刪除15呢,元素的個數太少以至於不能再旋轉,把12提上去就行了
在這裏插入圖片描述
在這裏插入圖片描述

2. B+ 樹

在這裏插入圖片描述

2.1 B+樹的特徵
  1. B+樹是 B樹的變體,性能更好,更穩定,MySQL就是B+樹
  2. 非葉子節點可以保存 n 個元素B樹是n-1個所以上面的的例子只能儲存2個)
  3. 所有的元素(節點數字和指向元素指針地址)都能在葉子節點裏找到,而且葉子本身就是按照關鍵字的大小順序連接
  4. 所有的非葉子節點可以看似索引,元素的[數字值]是兒子節點的最大(或者最小的)[數字值]
  5. 通常 B+樹上有 2個頭指針,一個指向根節點,一個子項關鍵字最小的節點,
  6. 所有的元素都能在葉子裏找到,上面的節點包含重複的元素。
  7. 根節點的最大的元素就是整個B樹的最大的元素
2.2 B+樹的查詢優勢
  1. B+樹中間節點不保存數據,所以磁盤也能容納更多的節點元素顯得矮胖
  2. B+樹必須查詢到葉子才能獲得數據,但是並不慢,而且更加穩定
  3. 對於外圍查找,B+樹只需要遍歷葉子節點即可。(數據只存在於葉子節點)

三、爲什麼使用B樹或者 B+樹?

數據庫的索引本身很大,不能直接全部讀取到內存中,只能磁盤分步讀取到內存中,因爲此磁盤的IO速度十分慢(比內存慢幾個數量級),**所以爲了儘量減少磁盤的IO,**二叉樹,紅黑樹這種高度很高的數就不適合,就是用B樹這種矮胖的結構。

1,主存(內存)存取原理

內存多次讀取數據之間的距離不會對速度產生任何影響,舉個例子

在這裏插入圖片描述
(1)讀取數據1,就去尋找0x0A地址,讀取數據2 找 0x0B
(2)讀取數據1,就去尋找0x0A地址,讀取數據6找 0x2C地址,
(3)(1)和(2)的耗時是相對的,這就是距離不會對速度產生任何影響

2.磁盤讀取數據的原理

索引一般在磁盤上,檢索磁盤需要磁盤的IO操作和內存的IO操作有很大的不同,主要是磁盤存在機械運動,耗時十分巨大。

2.1.磁盤讀取數據的過程

磁盤讀取數據時候,系統會將數據的地址給磁盤,磁盤確定數據的位置,**將磁頭移動道對應數據的磁道,(尋道時間)然後旋轉到對應的數據的地方(旋轉時間)**然後才能讀取到對應數據

2.2 局部性原理和磁盤預讀

1.預讀

(1)預讀產生原因:由於儲存介質機械運動的 原因,磁盤的讀取很慢,比內存差幾個數量級,所以要盡力減少此磁盤的IO次數,(減少機械運動的時間)
(2)預讀定義:舉例如果你只需要一個字節的數據,但是磁盤會直接讀取4000個字節(很多操作系統默認4K爲1頁)到內存,這樣做的理論依據是局部性原理
(3)預讀的長度爲頁(page)的整數倍,硬件和操作系統將內存和磁盤分爲頁(通常爲4KB大小)內存和磁盤通過頁爲數據單位交換數據,當 程序需要的數據不在內存中時候(數據不連續預讀失敗),會觸發一個缺頁異常,磁盤會更具缺失的數據的地址重新讀取數據和數據後的一頁或者幾頁的數據。因此:儘量保證數據連續,使用預讀減少IO
(4)總結:保證數據連續,使用預讀減少IO

2.局部性原理

(1)當一個數據被使用的時候,附近的數據很有可能也會被使用,
(2)運行期間需要的數據通常比較集中

四、InnoDB引擎性能優化。

yISAM引擎和InnoDB引擎的區別請看博客(重點)MySQL(入門篇26)聚簇索引和非聚簇索引的區別
在這裏插入圖片描述

(重點)1.爲什麼InnoDB所有表建議使用一個自增Id作爲主鍵索引?

1.1節約內存

輔助索引連接的都是主鍵索引的引用(如圖上),如果你用其他過長的索引會讓**輔助索引過長內存十分臃腫且浪費**

1.2 (自增id主鍵)會有連續的索引結構

由上面的內存分析可知道,如果連續的磁盤存儲,可以減少讀取的IO,mysql會根據主鍵插入適當的節點和位置,如果達到裝載因子(mysql默認15/16)就開闢一個新的頁(page)

如果使用自增主鍵,開闢新的頁就是連續開闢,減少IO。(如圖)
在這裏插入圖片描述
所以:
儘量使用一個自增的id作爲主鍵

文章參考
http://blog.codinglabs.org/articles/theory-of-mysql-index.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章