1. 程式人生 > >B+樹 && B+樹索引&&Cardinality值 ----- InnoDB儲存引擎內幕

B+樹 && B+樹索引&&Cardinality值 ----- InnoDB儲存引擎內幕

1.二叉查詢樹&平衡二叉樹

  • B+樹由二叉查詢樹+平衡二叉樹演化而來
    1.1下面來簡單介紹一下二叉查詢樹
  • 例子:
    在這裡i插入圖片描述
    上圖中:數字代表每個節點的鍵值
    特點:
  • 1.左子樹的鍵值總是<右子樹的鍵值
  • 2.右子樹的鍵值總是>左子樹的鍵值

若對該樹進行查詢,如查鍵值為5的記錄,先找到根6 因為6>5 往左子樹找 得到3 < 5 再找右子樹 找到鍵值 共需要3次

缺點
在這裡插入圖片描述
如果像上圖一樣查詢的效率就低下了

由此引入1.2AVL平衡二叉樹
AVL定義:

  • 1.首先符合二叉查詢樹定義
  • 2.滿足任何節點的兩個子樹高度差最大是1
    缺點:需要維護的代價非常大,一般需要1次或者多次左旋和右旋來得到插入或更新後樹的平衡性

    – 示例:
    在這裡插入圖片描述
    平衡樹多用於記憶體結構物件中,因此維護的開銷相對較小。

2.B+樹

一顆B+樹要滿足以下特點:

  • 1.有k個子樹其中間的節點就包含了k個元素 每個元素不存資料 只是索引(指標) 所有值都儲存在葉子節點中
  • 2.所有的葉子節點都包含了全部的元素資訊,包括指向該元素的指標,同時 葉子節點依照關鍵字的大小自小而大連結。
  • 3.所有中間節點元素都同時存在於子節點,在子節點元素中最大(最小)的
    簡單概括:
  • 1.子樹個數=非葉子節點數
  • 2.非葉子節點僅是索引不存值 可以有重複的元素
  • 3.葉子節點存值 用指標連線在一起
    在這裡插入圖片描述
    在這裡插入圖片描述

2.1B+樹的插入情況

插入的時候要保證插入後葉子節點依然排序 需要考慮以下三種情況:
在這裡插入圖片描述
舉例分析:

  • 1.插入鍵值28 leaf page& index page都沒有滿 符合第一種情況 直接插入就可以
    在這裡插入圖片描述

  • 2.插入鍵值70 Leaf Page值滿 Index Page未滿 符合第二種情況
    雖然沒有顯示,依然是雙向連結串列指標 存在的
    在這裡插入圖片描述

  • 3.插入鍵值95 Leaf Page & Index Page都滿了 需要做兩次拆分
    在這裡插入圖片描述

為了保持平衡對於新插入的鍵值需要做大量的拆分頁(split)操作。
由於B+樹主要用於磁碟,頁的拆分表示磁碟的操作,所以儘量減少頁的拆分操作。提供了旋轉操作(Rotation)


看一下旋轉發生的條件:

  • 1.Leaf Page已滿 左右兄弟節點沒有滿
  • 2.不做拆分 而是將記錄移到所在頁的兄弟節點上
  • 示例:插入70
    在這裡插入圖片描述

2.2B+樹的刪除操作

同樣也是滿足三種情況 B+樹的刪除操作同樣也要保證排序,根據其填充因子(fill factor 也就是非葉子節點部分 50%是最小值)的變化而衡量
在這裡插入圖片描述

示例
在這裡插入圖片描述

  • 1.刪除鍵值70 符合第一種情況
    在這裡插入圖片描述

  • 2.刪除鍵值25 同時是Index Page節點
    在這裡插入圖片描述

  • 3.刪除鍵值60 Fill Factor<50% 刪除Index Page後 再次需要合併 Index Page
    在這裡插入圖片描述

3.B+樹索引

在DB中的特點:高扇出性,B+樹的高度一般都是在2-4層 (查詢某鍵值只需要2-4次IO)
B+索引分類

  • 1.聚集索引(clustered index)
    聚集索引就是按照每張表的主鍵構造一顆B+樹,而且葉子節點就存放了表的所有行記錄資料,也稱聚集索引的葉子節點是資料頁。每個資料頁都由雙向連結串列進行連結。**每個表只能有一顆B+數進行排序 只有一個聚集索引 **。
    (接下來的表空間儲存分析只能以後補上了 目前還沒弄懂)
  • 2.輔助索引(Secondary Index 非聚集索引)
    葉子節點並不包含全部資料。葉子節點包含了鍵值&&書籤(bookmark)書籤帶領指向與索引相對應的行資料
    和聚集索引的關係
    在這裡插入圖片描述
    輔助索引不影響資料在聚集索引中的組織,每張表可以有多個輔助索引。
    InnoDB引擎遍歷輔助索引找到主鍵索引的主鍵,再通過主鍵索引找到行記錄。

3.1B+樹索引的管理

3.1.1B+樹索引的管理

建立和刪除有兩種:1.ALTER TABLE 2.CREATE | DROP INDEX

  • 1.ALTER TABLE
    在這裡插入圖片描述
  • 2.CREATE | DROP INDEX
    在這裡插入圖片描述

如果要檢視:show index from tb
在這裡插入圖片描述

接下來分析每個引數的具體含義

  • 1.Table:索引所在的表名
  • 2.Non_unique:非唯一索引 如果聚集索引(primary key = 0)
  • 3.Key_name:索引名字
  • 4.Seq_in_index:索引中該列的位置
  • 5.Column_name:索引列的名稱
  • 6.Collation:列以什麼方式儲存在索引中。兩種結果 A | NULL A:B+樹索引 表示排序的 NULL:如果使用了Heap儲存引擎 建立Hash索引 顯示NULL.HASH根據Hash桶存放索引資料 不對資料排序
  • 7.cardinality :很關鍵的值 表示索引中唯一值的數目的估計值。 行數應儘可能為1.若非常小 考慮是否刪除該索引
  • 8.Sup_part:是否是列的部分索引(列只有部分被索引)NULL:整列被索引
  • 9.Packed:關鍵字如何被壓縮
  • 10.NULL:是否索引列含有NULL值
  • 11.Index_type:索引型別 InnoDB只支援B+樹 顯示為BTREE
  • 12.Comment:註釋

單獨介紹一下Cardinality: 該值優化器根據該值判斷是否使用這個索引 問題:不是實時更新(每次更新索引不會更新這個值) 建議更新完後使用 ANALYZE TABLE 命令

  • 1)Cardinality為NULL,在某些情況下可能發生索引建立了確沒有用 同樣的語句 一種走索引 另一種走全表掃描。建議:在非高峰時期,對應用程式下的幾張核心表做ANALYZE TABLE操作。

3.1.2Fast Index Creation(FIC):

一般建索引的DDL操作過程:
在這裡插入圖片描述

總結一下:1)新建臨時表(表結構用alter table實現) 2)把資料匯入到tmp表中 3)刪原表 4)把臨時表重名為原來的表
這種方式非常繁瑣 — 引入了FIC(快速索引建立)

輔助索引建立|刪除流程:

  • 1)儲存引擎對建索引的表上加s鎖 不需要刪表 重建表 快速了 資料庫可用性得到提高
  • 2)刪除輔助索引 需要更新內部檢視 將輔助索引的空間標記為可用 同時刪除DB內部檢視上對該表索引定義即可

3.1.3Online Schema Change(有空要做個實驗了!!!)

MySQL 大表線上DML神器–pt-online-schema-change
pt-online-schema-change的實現原理

OSC實現過程:
在這裡插入圖片描述
在這裡插入圖片描述

3.1.4DDL線上操作

MySQL5.6版本支援Online DDL操作,允許輔助索引建立同時 還允許其他INSERT DELETE UPDATE (DML)操作
以下幾類DDL可以通過線上方式進行操作:

  • 1.輔助索引的建立和刪除
  • 2.改變自增長
  • 3.新增或刪除外來鍵約束
  • 4.列的重新命名
    語法:
    在這裡插入圖片描述

ALGORITHM:指定了建立或刪除索引的演算法。
COPY(按照5.1版本前工作 即要複製表進行建立刪除) INPLACE(不需要建立臨時表) DEFAULT(根據old_alter_table來判斷是通過INPLACE | COPY演算法 預設值為OFF 使用inplace的方式)
LOCK:索引建立或刪除時對錶新增鎖的情況。
(1)NONE:執行索引或者刪除操作時 對目標表不新增任何的鎖 即事務仍然可以進行讀寫操作 不會收到阻塞。 可以獲得最大併發度。
(2)SHARE:類似FIC 建立或刪除索引加S鎖。對於併發讀事務依然可以執行 遇到寫事務 會發生等待操作。如果儲存引擎支援SHARE模式 會返回一個錯誤資訊。
(3)EXCLUSIVE:執行索引建立或刪除操作時,對目標表加上一個X鎖 讀寫事務不能進行 所以會阻塞所有的執行緒,和COPY方式執行得到的狀態類似,但不需要像COPY方式那樣建立一張臨時表。
(4)DEFAULT:首先判斷當前操作是否可以用NONE模式,不能就判斷是否使用SHARE模式了,最後判斷是否可以使用EXCLUSIVE模式

實現Online DDL的原理:在執行建立或者刪除操作的同時,將INSERT UPDATE DELETE這類DML操作日誌寫入到一個快取中。待完成索引後重新應用到表上,達到資料一致性。

4.Cardinality值:

  • 新增索引的條件:在訪問表中很少使用一部分時使用B+樹索引有意義。具有高選擇性的 並且抽取小欄位的資料可以建B+樹索引
  • 高選擇性:取值範圍大 如姓名 ID等大範圍 (低選擇性: 取值範圍小 如性別欄位 地區欄位 型別欄位 型別欄位 可取值的範圍很小)

4.1統計Cardinality值:

考慮統計的因素:(1)統計頻率 觸發更新為update & insert 更新一次就統計的話 頻繁了(2)統計表數量級過大 統計時間長不好

  • 更新Cardinality策略:
  • 1.表中1/16的資料已發生過變化
  • 2.stat_modified_counter>2000 000 000(防止更新次數只在一行 若更新了該次數 也需要更新統計)

取樣過程 預設InnoDB儲存引擎對8個葉子節點進行取樣:

  • 取得B+樹索引中葉子節點的數量 記為A
  • 隨機取得B+樹索引中的8個葉子節點 統計每個頁不同記錄的個數 即為P1,P2…P8
  • 根據取樣資訊給出Cardinality的預估值:Cardinality=(P1+P2+…P8)*A/8
    可以得到統計取樣值不是精確值 可能每次得到的值都不一樣
    在這裡插入圖片描述