1. 程式人生 > >MySQL和B樹的那些事

MySQL和B樹的那些事

一、零鋪墊

    在介紹B樹之前,先來看另一棵神奇的樹——二叉排序樹(Binary Sort Tree),首先它是一棵樹,“二叉”這個描述已經很明顯了,就是樹上的一根樹枝開兩個叉,於是遞迴下來就是二叉樹了(下圖所示),而這棵樹上的節點是已經排好序的,具體的排序規則如下:

  • 若左子樹不空,則左子樹上所有節點的值均小於它的根節點的值
  • 若右子樹不空,則右子樹上所有節點的值均大於它的根節點的值
  • 它的左、右子樹也分別為二叉排序數(遞迴定義)

    從圖中可以看出,二叉排序樹組織資料時,用於查詢是比較方便的,因為每次經過一次節點時,最多可以減少一半的可能,不過極端情況會出現所有節點都位於同一側,直觀上看就是一條直線,那麼這種查詢的效率就比較低了,因此需要對二叉樹左右子樹的高度進行平衡化處理,於是就有了平衡二叉樹(Balenced Binary Tree)。

   所謂“平衡”,說的是這棵樹的各個分支的高度是均勻的,它的左子樹和右子樹的高度之差絕對值小於1,這樣就不會出現一條支路特別長的情況。於是,在這樣的平衡樹中進行查詢時,總共比較節點的次數不超過樹的高度,這就確保了查詢的效率(時間複雜度為O(logn))。

二、B樹的起源

     B樹,最早是由德國電腦科學家Rudolf Bayer等人於1972年在論文 《Organization and Maintenance of Large Ordered Indexes》提出的,不過我去看了看原文,發現作者也沒有解釋為什麼就叫B-trees了,所以把B樹的B,簡單地解釋為Balanced或者Binary都不是特別嚴謹,也許作者就是取其名字Bayer的首字母命名的也說不定啊……

三、B樹長啥樣

    還是直接看圖比較清楚,圖中所示,B樹事實上是一種平衡的多叉查詢樹,也就是說最多可以開m個叉(m>=2),我們稱之為m階b樹,為了體現本部落格的良心之處,不同於其他地方都能看到2階B樹,這裡特意畫了一棵5階B樹 。

總的來說,m階B樹滿足以下條件:

  • 每個節點至多可以擁有m棵子樹
  • 根節點,只有至少有2個節點(要麼極端情況,就是一棵樹就一個根節點,單細胞生物,即是根,也是葉,也是樹)。
  • 非根非葉的節點至少有的Ceil(m/2)個子樹(Ceil表示向上取整,圖中5階B樹,每個節點至少有3個子樹,也就是至少有3個叉)。
  • 非葉節點中的資訊包括[n,A0,K1,A1,K2,A2,…,Kn,An],,其中n表示該節點中儲存的關鍵字個數,K為關鍵字且Ki<Ki+1,A為指向子樹根節點的指標。
  • 從根到葉子的每一條路徑都有相同的長度,也就是說,葉子節在相同的層,並且這些節點不帶資訊,實際上這些節點就表示找不到指定的值,也就是指向這些節點的指標為空。

    B樹的查詢過程和二叉排序樹比較類似,從根節點依次比較每個結點,因為每個節點中的關鍵字和左右子樹都是有序的,所以只要比較節點中的關鍵字,或者沿著指標就能很快地找到指定的關鍵字,如果查詢失敗,則會返回葉子節點,即空指標。

例如查詢圖中字母表中的K

  1. 從根節點P開始,K的位置在P之前,進入左側指標
  2. 左子樹中,依次比較C、F、J、M,發現K在J和M之間
  3. 沿著J和M之間的指標,繼續訪問子樹,並依次進行比較,發現第一個關鍵字K即為指定查詢的值

四、Plus版——B+樹

作為B樹的加強版,B+樹與B樹的差異在於

  • 有n棵子樹的節點含有n個關鍵字(也有認為是n-1個關鍵字)
  • 所有的葉子節點包含了全部的關鍵字,及指向含這些關鍵字記錄的指標,且葉子節點本身根據關鍵字自小而大順序連線
  • 非葉子節點可以看成索引部分,節點中僅含有其子樹(根節點)中的最大(或最小)關鍵字

    B+樹的查詢過程,與B樹類似,只不過查詢時,如果在非葉子節點上的關鍵字等於給定值,並不終止,而是繼續沿著指標直到葉子節點位置。因此在B+樹,不管查詢成功與否,每次查詢都是走了一條從根到葉子節點的路徑。

五、MySQL是如何使用B樹的

說明:事實上,在MySQL資料庫中,諸多儲存引擎使用的是B+樹,即便其名字看上去是BTREE。

1、innodb的索引機制

先以innodb儲存引擎為例,說明innodb引擎是如何利用B+樹建立索引的。首先建立一張表:zodiac,並插入一些資料

CREATE TABLE `zodiac` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` char(4) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `index_name` (`name`)
); 

insert zodiac(id,name) values(1,''); &nbsp;
insert zodiac(id,name) values(2,''); &nbsp;
insert zodiac(id,name) values(3,''); &nbsp;
insert zodiac(id,name) values(4,''); &nbsp;
insert zodiac(id,name) values(5,''); &nbsp;
insert zodiac(id,name) values(6,''); &nbsp;
insert zodiac(id,name) values(7,''); &nbsp;
insert zodiac(id,name) values(8,''); &nbsp;
insert zodiac(id,name) values(9,'');
insert zodiac(id,name) values(10,''); &nbsp;
insert zodiac(id,name) values(11,''); &nbsp;
insert zodiac(id,name) values(12,'');

   對於innodb來說,只有一個數據檔案,這個資料檔案本身就是用B+樹形式組織B+樹每個節點的關鍵字就是表的主鍵,因此innodb的資料檔案本身就是主索引檔案,如下圖所示,主索引中的葉子頁(leaf page)包含了資料記錄,但非葉子節點只包含了主鍵,術語“聚簇”表示資料行和相鄰的鍵值緊湊地儲存在一起,因此這種索引被稱為聚簇索引,或聚集索引。

    這種索引方式,可以提高資料訪問的速度,因為索引和資料是儲存在同一棵B樹之中,從聚簇索引中獲取資料通常比在非聚簇索引中要來得快。

   所以可以說,innodb的資料檔案是依靠主鍵組織起來的,這也就是為什麼innodb引擎下建立的表,必須指定主鍵的原因,如果沒有顯式指定主鍵,innodb引擎仍然會對該表隱式地定義一個主鍵作為聚簇索引。

    同樣innodb的輔助索引,如下圖所示,假設這些字元是按照生肖的順序排列的(其實我也不知道具體怎麼實現,不要在意這些細節,就是舉個例子),其葉子節點中也包含了記錄的主鍵,因此innodb引擎在查詢輔助索引的時候會查詢兩次,首先通過輔助索引得到主鍵值,然後再查詢主索引略微有點囉嗦。。。

2、MyISAM的索引機制

    MyISAM引擎同樣也使用B+樹組織索引,如下圖所示,假設我們的資料不是按照之前的順序插入的,而是按照圖中的是順序插入表,可以看到MyISAM引擎下B+樹葉子節點中包含的是資料記錄的地址(可以簡單理解為“行號”),而MyISAM的輔助索引在結構上和主索引沒有本質的區別,同樣其葉子節點也包含了資料記錄的地址,稍微不同的是輔助索引的關鍵字是允許重複。

六、簡單對比

1、Innodb輔助索引的葉子節點儲存的不是地址,而是主鍵值,這樣的策略減少了當出現行移動或者資料頁分裂時輔助索引的維護工作,雖然使用主鍵值當作指標會讓輔助索引佔用更多空間,但好處是,Innodb在移動行時無需更新輔助索引中的主鍵值,而MyISAM需要調整其葉子節點中的地址。

2、innodb引擎下,資料記錄是儲存在B+樹的葉子節點(大小相當於磁碟上的頁)上,當插入新的資料時,如果主鍵的值是有序的,它會把每一條記錄都儲存在上一條記錄的後面,但是如果主鍵使用的是無序的數值,例如UUID,這樣在插入資料時Innodb無法簡單地把新的資料插入到最後,而是需要為這條資料尋找合適的位置,這就額外增加了工作,這就是innodb引擎寫入效能要略差於MyISAM的原因之一。

Innodb和MyISAM索引的抽象圖

相關推薦

MySQLB那些

一、零鋪墊     在介紹B樹之前,先來看另一棵神奇的樹——二叉排序樹(Binary Sort Tree),首先它是一棵樹,“二叉”這個描述已經很明顯了,就是樹上的一根樹枝開兩個叉,於是遞迴下來就是二叉樹了(下圖所示),而這棵樹上的節點是已經排好序的,具體的排序規則如下: 若左子樹不空,則左子樹上所有

Mysql InnoDB B+索引雜湊索引的區別? MongoDB 為什麼使用B-?

B-樹和B+樹最重要的一個區別就是B+樹只有葉節點存放資料,其餘節點用來索引,而B-樹是每個索引節點都會有Data域。 B+樹 B+樹是為磁碟及其他儲存輔助裝置而設計一種平衡查詢樹(不是二叉樹)。B+樹中,所有記錄的節點按大小順序存放在同一層的葉節點中,各葉

MySQL索引 B+索引雜湊索引的區別

備註:先說下,在MySQL文件裡,實際上是把B+樹索引寫成了BTREE,例如像下面這樣的寫法: CREATE TABLE t( aid int unsigned not null auto_increment, userid int unsigned no

B-B+的應用:數據搜索和數據庫索引

深度 出現 通過 都在 def 查找樹 兩個指針 屬性排序 n+1 B-樹 1 .B-樹定義 B-樹是一種平衡的多路查找樹,它在文件系統中很有用。 定義:一棵m 階的B-樹,或者為空樹,或為滿足下列特性的m 叉樹:⑴樹中每個結點至多有m 棵子樹;⑵若根結點不是葉子結點,

BB-B+B*介紹,B+更適合做文件索引的原因

二叉搜索樹 margin 鏈表 重建 影響 不足 原來 之間 復制 今天看數據庫,書中提到:由於索引是采用 B 樹結構存儲的,所以對應的索引項並不會被刪除,經過一段時間的增刪改操作後,數據庫中就會出現大量的存儲碎片, 這和磁盤碎片、內存碎片產生原理是類似的,這些存儲碎片不僅

BB+的總結

href 直接插入 也有 新的 img 結束 提高 通過 我們 https://www.cnblogs.com/George1994/p/7008732.html B樹和B+樹的總結 B樹 為什麽要B樹 磁盤中有兩個機械運動的部分,分別是盤片旋轉和磁臂

BB+的插入、刪除圖文詳解

留言 使用 結構 調整 -i 詳細 樹的高度 目的 根據 簡介:本文主要介紹了B樹和B+樹的插入、刪除操作。寫這篇博客的目的是發現沒有相關博客以舉例的方式詳細介紹B+樹的相關操作,由於自身對某些細節也感到很迷惑,通過查閱相關資料,對B+樹的操作有所頓悟,寫下這篇博客以做記錄

BB+

樹的高度 需要 比較 詳細 細節 子類 是我 導致 相關 B樹和B+樹 簡介:本文主要介紹了B樹和B+樹的插入、刪除操作。寫這篇博客的目的是發現沒有相關博客以舉例的方式詳細介紹B+樹的相關操作,由於自身對某些細節也感到很迷惑,通過查閱相關資料,對B+樹的操作有所頓悟,寫下這

WebSocket 的那些(一)

com lis 都沒有 情況下 系統 並不是 任務管理 js實現 因此   我的策劃大佬離職了,在他go之前我都沒有解決好一個問題,感覺如果我換了工作面試的時候,別人問到 “你在做項目的時候,遇到的最頭疼的問題是什麽,是怎麽解決的?”,首先想到的應該也是他,今天感覺是時候寫

B-B+的應用

例如 討論 計算 相關信息 net 基本上 ref CA roc 1 .B-樹定義 B-樹是一種平衡的多路查找樹,它在文件系統中很有用。 定義:一棵m 階的B-樹,或者為空樹,或為滿足下列特性的m 叉樹:⑴樹中每個結點至多有m 棵子樹;⑵若根結點不是葉子結點,則至少有兩

B, B-,B+,B*的區別

cal 查詢 空間 復制 進入 使用 鏈表 有關 但是 B樹: B樹的搜索,從根結點開始,如果查詢的關鍵字與結點的關鍵字相等,那麽就命中; 否則,如果查詢關鍵字比結點關鍵字小,就進入左兒子;如果比結點關鍵字大,就進入 右兒子;如果左兒子或右兒子的指針為空,則報告找不到相應的

淺談MySQLB索引與索引優化

成本 情況 但是 數據行 eat bst tree bfs 優化 前言 MySQL的MyISAM、InnoDB引擎默認均使用B+樹索引(查詢時都顯示為“BTREE”),本文討論兩個問題: 為什麽MySQL等主流數據庫選擇B+樹的索引結構? 如何基於索引結構,理解常見的MyS

引用指標的那些

2.3.1 引用 引用並非物件,相反的,它只是為一個已存在物件所起的另外一個名字。 示例: int ival = 1024; int &refVal = ival; Tips: 1.除2種情況外,引用的型別要和與之繫結的物件嚴格匹配 2.引用必須被初始化,且一旦初始化後,它和初始值物件一直繫結

B-B+的應用 資料搜尋資料庫索引

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

深入理解mysql資料庫B+索引

索引的作用: 首先索引通俗來講就像書的目錄,通過索引可以快速查詢對應資料,但這僅僅是表面上的,索引主要作用有3點,這僅僅算作其中1點。以下是鄙人的理解: 通過索引可以減少資料的掃描量(例如上面提到的將全書掃描,變成了根據目錄找) 索引可以把對硬碟的隨機IO變為順序IO()

多叉——BB+

目錄   1 介紹 2 B樹 2.1 B樹的定義 2.2 B樹的查詢 2.3 B樹的插入 2.4 B樹的刪除 2.5 B樹的應用 3 B+樹 3.1 定義 3.2 B+樹的插入 3.3 B+樹的刪除 1 介紹 樹家族是為了實現方便

雜談——關於“域”“跨域”那些

注:本文主要用於自主總結,後期會更新。如果要最全面的,可以參考大神的文章正確面對跨域、別慌 好啦,進入正題。 今天我們來了解一下“跨域”。 究竟什麼是跨域呢?首先我們得先了解一下什麼是域。 一、域是什麼? 在今天很多人都有意識或無意識的跟域這個東西打過交道。如果你在公司裡使用電腦

C++遊戲開發那些,告訴你怎麼用C++縱橫遊戲程式設計!

C語言和C++ C 語言可以說是一門設計的非常成功的語言。但是C語言沒有OOP的特性,在做一些大型專案的時候力不從心。一些大型的C專案,隨著專案的臃腫,人類基本沒辦 法維護這個專案了。要維護這麼龐大的專案而又不出錯,只能加入一些OOP特性重構,有經驗的C程式設計師寫著寫著,很多概念就類似C+

Java HTTP 的那些之模擬 HTTP 請求

一、使用 HttpURLConnection 傳送 HTTP 請求 Java 自帶的 java.net 這個包中包含了很多與網路請求相關的類,但是對於我們來說,最關心的應該是 HttpURLConnection 這個類了。 1.1 建立 HTTP 連線物件 要得到一個 

深入理解資料庫索引採用BB+的原因

         前面幾篇關於資料庫底層磁碟檔案讀取,資料庫索引實現細節進行了深入的研究,但是沒有串聯起來的講解為什麼資料庫索引會採用B樹和B+樹而不是其他的資料結構,例如平衡二叉樹、連結串列等,因此,本文打算從資料庫檔案儲存以及讀取說起,講解資料庫索引的由來。