MySQL 索引B 樹原理,以及建索引的幾大原則

2021-09-19 07:41:07 字數 3012 閱讀 9935

一、mysql中的索引

在 mysql 中,主要有四種型別的索引,分別為: b-tree 索引, hash 索引, fulltext 索引和 r-tree 索引。

b-tree 索引是 mysql 資料庫中使用最為頻繁的索引型別,除了 archive 儲存引擎之外的其他所有的儲存引擎都支援 b-tree 索引。archive 引擎直到 mysql 5.1 才支援索引,而且只支援索引單個 auto_increment 列。

不僅僅在 mysql 中是如此,實際上在其他的很多資料庫管理系統中b-tree 索引也同樣是作為最主要的索引型別,這主要是因為 b-tree 索引的儲存結構在資料庫的資料檢索中有非常優異的表現。

一般來說, mysql 中的 b-tree 索引的物理檔案大多都是以 balance tree 的結構來儲存的,也就是所有實際需要的資料都存放於 tree 的 leaf node(葉子節點) ,而且到任何乙個 leaf node 的最短路徑的長度都是完全相同的,所以我們大家都稱之為 b-tree 索引。當然,可能各種資料庫(或 mysql 的各種儲存引擎)在存放自己的 b-tree 索引的時候會對儲存結構稍作改造。如 innodb 儲存引擎的 b-tree 索引實際使用的儲存結構實際上是 b+tree,也就是在 b-tree 資料結構的基礎上做了很小的改造,在每乙個leaf node 上面出了存放索引鍵的相關資訊之外,還儲存了指向與該 leaf node 相鄰的後乙個 leafnode 的指標資訊(增加了順序訪問指標),這主要是為了加快檢索多個相鄰 leaf node 的效率考慮。

innodb是mysql的預設儲存引擎(mysql5.5.5之前是myisam)

可能對於沒有了解過索引的猿友這樣看這篇文章十分吃力,這類猿友有必要先對mysql索引有個大體的了解,可以看看小寶鴿另外一篇文章: 資料庫查詢優化——mysql索引。看完這篇文章我們再回頭看看上面的文字說明吧。

接下來我們先看看b-樹、b+樹的概念。弄清楚,為什麼加了索引查詢速度會加快?

二、b-樹、b+樹概念

b樹,即二叉搜尋樹:

所有非葉子結點至多擁有兩個兒子(left和right);

所有結點儲存乙個關鍵字;

非葉子結點的左指標指向小於其關鍵字的子樹,右指標指向大於其關鍵字的子樹;

b-樹是一種多路搜尋樹(並不是二叉的):

定義任意非葉子結點最多只有m個兒子;且m>2;

根結點的兒子數為[2, m];

除根結點以外的非葉子結點的兒子數為[m/2, m];

每個結點存放至少m/2-1(取上整)和至多m-1個關鍵字;(至少2個關鍵字)

非葉子結點的關鍵字個數=指向兒子的指標個數-1;

非葉子結點的關鍵字:k[1], k[2], …, k[m-1];且k[i] < k[i+1];

非葉子結點的指標:p[1], p[2], …, p[m];其中p[1]指向關鍵字小於k[1]的子樹,p[m]指向關鍵字大於k[m-1]的子樹,其它p[i]指向關鍵字屬於(k[i-1], k[i])的子樹;

所有葉子結點位於同一層;

b-樹的搜尋,從根結點開始,對結點內的關鍵字(有序)序列進行二分查詢,如果命中則結束,否則進入查詢關鍵字所屬範圍的兒子結點;重複,直到所對應的兒子指標為空,或已經是葉子結點;

b-樹的特性:

關鍵字集合分布在整顆樹中;

任何乙個關鍵字出現且只出現在乙個結點中;

搜尋有可能在非葉子結點結束;

其搜尋效能等價於在關鍵字全集內做一次二分查詢;

自動層次控制;

由於限制了除根結點以外的非葉子結點,至少含有m/2個兒子,確保了結點的至少利用率。

所以b-樹的效能總是等價於二分查詢(與m值無關),也就沒有b樹平衡的問題;

由於m/2的限制,在插入結點時,如果結點已滿,需要將結點**為兩個各佔m/2的結點;刪除結點時,需將兩個不足m/2的兄弟結點合併;

b+樹b+樹是b-樹的變體,也是一種多路搜尋樹:

其定義基本與b-樹同,除了:

非葉子結點的子樹指標與關鍵字個數相同;

非葉子結點的子樹指標p[i],指向關鍵字值屬於[k[i], k[i+1])的子樹(b-樹是開區間);

為所有葉子結點增加乙個鏈指標;

所有關鍵字都在葉子結點出現;

b+的搜尋與b-樹也基本相同,區別是b+樹只有達到葉子結點才命中(b-樹可以在非葉子結點命中),其效能也等價於在關鍵字全集做一次二分查詢;

b+的特性:

所有關鍵字都出現在葉子結點的鍊錶中(稠密索引),且鍊錶中的關鍵字恰好是有序的;

不可能在非葉子結點命中;

非葉子結點相當於是葉子結點的索引(稀疏索引),葉子結點相當於是儲存(關鍵字)資料的資料層;

更適合檔案索引系統;

三、建索引的幾大原則

最左字首匹配原則,非常重要的原則,mysql會一直向右匹配直到遇到範圍查詢(>、<、between、like)就停止匹配,比如a = 1 and b = 2 and c > 3 and d = 4 如果建立(a,b,c,d)順序的索引,d是用不到索引的,如果建立(a,b,d,c)的索引則都可以用到,a,b,d的順序可以任意調整。

=和in可以亂序,比如a = 1 and b = 2 and c = 3 建立(a,b,c)索引可以任意順序,mysql的查詢優化器會幫你優化成索引可以識別的形式

盡量選擇區分度高的列作為索引,區分度的公式是count(distinct col)/count(*),表示欄位不重複的比例,比例越大我們掃瞄的記錄數越少,唯一鍵的區分度是1,而一些狀態、性別字段可能在大資料面前區分度就是0,那可能有人會問,這個比例有什麼經驗值嗎?使用場景不同,這個值也很難確定,一般需要join的字段我們都要求是0.1以上,即平均1條掃瞄10條記錄

索引列不能參與計算,保持列「乾淨」,比如from_unixtime(create_time) = 』2014-05-29』就不能使用到索引,原因很簡單,b+樹中存的都是資料表中的字段值,但進行檢索時,需要把所有元素都應用函式才能比較,顯然成本太大。所以語句應該寫成create_time = unix_timestamp(』2014-05-29』);

盡量的擴充套件索引,不要新建索引。比如表中已經有a的索引,現在要加(a,b)的索引,那麼只需要修改原來的索引即可

原文:參考:與hash索引型別對比

mysql 新增b樹索引 Mysql之B樹索引

聚集索引 簡單概念 乙個表中根據主鍵建立的一棵b 樹,索引的葉子節點存放了表中所有的記錄,儲存記錄在物理位置上是連續的,乙個葉子節點存放一條對應的記錄 ps 是根據主鍵建立的b 樹,葉子節點存資料記錄 舉個例子 以漢語字典為例 漢語字典的正文本身就是乙個聚集索引,比如我們要查 安 字,由於漢語詞典的...

MYSQL索引原理B 樹

書中 mysql技術內部innodb儲存引擎 有所有你的疑惑解答 mysql 索引總結 mysql索引是b 樹,一般高度在2 4層,機械磁碟每秒可以做100此i o,索引2 4次需要花費0.04s的時間,非常好 mysql使用的是聚簇索引,一般是主鍵索引是聚簇索引,而輔助索引是非聚簇索引 聚簇索引 ...

MySQL索引原理(b 樹)

索引目的 索引的目的在於提高查詢效率,可以模擬字典,如果要查 mysql 這個單詞,我們肯定需要定位到m字母,然後從下往下找到y字母,再找到剩下的sql。如果沒有索引,那麼你可能需要把所有單詞看一遍才能找到你想要的,如果我想找到m開頭的單詞呢?或者ze開頭的單詞呢?是不是覺得如果沒有索引,這個事情根...