日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

mysql b 树原因_复习系列之数据库(四):MySQL为什么采用B+树作为索引结构?

發布時間:2024/7/23 数据库 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 mysql b 树原因_复习系列之数据库(四):MySQL为什么采用B+树作为索引结构? 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

MySQL中數據是索引組織表,即表中數據按照主鍵順序存放。所以就可以基于索引這種數據結構實現一些高級算法,來提高檢索效率。

常見的查找算法

順序查找:復雜度O(n),在數據量大時,效率很低

二分查找:在有序為前提,復雜度O(logn)

hash查找:無法滿足范圍查找

二叉樹查找:O(logn),每個節點只能有一個左節點和一個右節點

試著用二叉樹來構造一種索引方式

為什么MySQL沒有采用二叉樹來構造索引呢?

由磁盤的物理結構決定的。

首先,二叉樹中每個節點只能有一個左節點和一個右節點,直接導致樹的高度很高,邏輯上相近的節點,無法利用局部性,相鄰節點沒法直接通過指針相連,可能需要返回上層節點重復遞歸找到結果,效率低。

其次,當數據量大時,內存不夠,大部分數據只能存放在磁盤上,只有在需要的時候才加載到內存中,但是磁盤讀取速度顯然與內存差很多,大部分時間會阻塞在IO上面,為了減少磁盤IO次數,上面這些傳統的樹無法滿足。

磁盤結構

下面是磁盤整體結構示意圖

其中,磁盤可以轉動(各個磁盤必須同步轉動)。每個磁頭負責存取一個磁盤的內容。磁頭不能轉動,但是可以沿磁盤半徑方向運動(實際是斜切向運動)。

盤片結構示意圖

盤片被劃分成一系列同心環,圓心是盤片中心,每個同心環叫做一個磁道,所有半徑相同的磁道組成一個柱面。

磁道被沿半徑線劃分成一個個小的段,每個段叫做一個扇區,每個扇區是磁盤的最小存儲單元。

磁盤如何讀取數據?

磁盤如何可以提高IO效率?

為了提高效率,要盡量減少磁盤I/O,磁盤往往不是嚴格按需讀取,而是每次都會預讀,即使只需要一個字節,磁盤也會從這個位置開始,順序向后讀取一定長度的數據放入內存。由于磁盤順序讀取的效率很高(不需要尋道時間,只需很少的旋轉時間),因此對于具有局部性的程序來說,預讀可以提高I/O效率。

預讀的長度一般為頁(page)(在許多操作系統中,頁的大小通常為4k)的整倍數。主存和磁盤以頁為單位交換數據。

當程序要讀取的數據不在主存中時,會觸發一個缺頁異常,此時系統會向磁盤發出讀盤信號,磁盤會找到數據的起始位置并向后連續讀取一頁或幾頁載入內存中,然后異常返回,程序繼續運行。

為了減少磁盤 IO 次數,B-/B+樹應運而生。

B-/B+樹

B-樹

為了更快,B-樹每次將范圍分割為多個區間,區間越多,定位數據越快越精確。

所以新建節點時,直接申請頁大小的空間,計算機內存分配是按頁對齊的,這樣就實現了一個節點只需要一次 IO。那么總 IO 的次數就縮減為了 log n 次。

下面是一棵簡化的B-樹:

B-樹的每個節點是 n 個有序的序列(a1,a2,a3…an),并將該節點的子節點分割成 n+1 個區間來進行索引(X1< a1, a2 < X2 < a3, … , an+1 < Xn < anXn+1 > an)。每個 key 值緊跟著 data 域,B-樹的 key 和 data 是聚合在一起的。

B-樹的如何進行查找的?

比如上圖中,若搜索 key 為 25 節點的 data,首先在根節點進行二分查找(因為 keys 有序,二分最快),判斷 key 25 小于 key 50,所以定位到最左側的節點,此時進行一次磁盤 IO,將該節點從磁盤讀入內存,接著繼續進行上述過程,直到找到該 key 為止。

B+樹

B+樹是B-樹的變種,它與B-樹的不同之處在于:

在B+樹中,key 副本存儲在內部節點,真正的 key 和 data 存儲在葉子節點上 。

n 個 key 值的節點指針域為 n 而不是 n+1。

為了增加 區間訪問性,一般會對B+樹做一些優化,增加了順序訪問指針。

下面是一棵簡化的B+樹:

因為內節點并不存儲 data,所以一般B+樹的葉節點和內節點大小不同,而B-樹的每個節點大小一般是相同的,為一頁。

因為增加了順序訪問指針,圖中如果要查詢key為從55到62的所有數據記錄,當找到50后,只需順著節點和指針順序遍歷就可以一次性訪問到所有數據節點,極大提到了區間查詢效率。

B-樹與B+樹區別

1.B+樹內節點不存儲數據,所有 data 存儲在葉節點導致查詢時間復雜度固定為 log n。而B-樹查詢時間復雜度不固定,與 key 在樹中的位置有關,最好為O(1)。

如上圖,如果查找50,剛好第一次就可以查找出來,所以最好情況是O(1)。由于B+樹所有的 data 域都在根節點,所以查詢 key 為 50的節點必須從根節點索引到葉節點,時間復雜度固定為 O(log n)。

2.B+樹葉節點兩兩相連可大大增加區間訪問性,可使用在范圍查詢等,而B-樹每個節點 key 和 data 在一起,則無法區間查找。

B+樹可以很好的利用局部性原理,若我們訪問節點 key為 50,則 key 為 55、60、62 的節點將來也可能被訪問,我們可以利用磁盤預讀原理提前將這些數據讀入內存,減少了磁盤 IO 的次數。當然B+樹也能夠很好的完成范圍查詢。比如查詢 key 值在 50-70 之間的節點。

3.B+樹更適合外部存儲。由于內節點無 data 域,每個節點能索引的范圍更大更精確

由于B-樹節點內部每個 key 都帶著 data 域,而B+樹節點只存儲 key 的副本,真實的 key 和 data 域都在葉子節點存儲。由于磁盤 IO 數據大小是固定的,在一次 IO 中,單個元素越小,量就越大。這就意味著B+樹單次磁盤 IO 的信息量大于B-樹,從這點來看B+樹相對B-樹磁盤 IO 次數少。

MySQL索引實現

在MySQL中,索引屬于存儲引擎級別的概念,不同存儲引擎對索引的實現方式是不同的,本文主要討論MyISAM和InnoDB兩個存儲引擎的索引實現方式。

索引分為:

聚集索引(Primary key):按照每張表的主鍵構造一棵B+樹,同時葉子節點中存放的即為整張表的行記錄數據,也將聚集索引的葉子節點稱為數據頁。每個數據頁都通過一個雙向鏈表來進行鏈接。每張表只能擁有一個聚集索引。

輔助索引(Secondary key):葉子節點并不包含行記錄的全部數據。葉子節點除了包含鍵值以外,還包含一個書簽,該書簽找到與索引相對應的行數據。每張表可以有多個輔助索引。

MyISAM引擎的實現

下圖是MyISAM索引的原理圖:

在MyISAM中,主索引和輔助索引在結構上沒有任何區別,只是主索引要求key是唯一的,而輔助索引的key可以重復。如果我們在Col2上建立一個輔助索引,則此索引的結構如下圖所示:

InnoDB引擎的實現

而在InnoDB中,表數據文件本身就是按B+Tree組織的一個索引結構,這棵樹的葉節點data域保存了完整的數據記錄。

這個索引的key是數據表的主鍵,因此InnoDB表數據文件本身就是主索引。

下圖是InnoDB主索引示意圖:

可以看到葉節點包含了完整的數據記錄。這種索引叫做聚集索引。因為InnoDB的數據文件本身要按主鍵聚集,所以InnoDB要求表必須有主鍵(MyISAM可以沒有)。

下圖為定義在Col3上的一個輔助索引:

這里以英文字符的ASCII碼作為比較準則。輔助索引搜索需要檢索兩遍索引:首先檢索輔助索引獲得主鍵,然后用主鍵到主索引中檢索獲得記錄。

這里就很容易明白為什么不建議使用過長的字段作為主鍵,因為所有輔助索引都引用主索引,過長的主索引會令輔助索引變得過大。

非單調的主鍵會造成在插入新記錄時數據文件為了維持B+Tree的特性而頻繁的分裂調整,十分低效,而使用自增字段作為主鍵則是一個很好的選擇。

數據的查找

1、精確查找:?select * from user_info where id = 23

內存中找到根節點,根節點二分查找確定范圍,逐層向下查找,讀取葉子節點,通過二分查找找到記錄或未命中。

2、索引范圍查找:select * from user_info where id >= 18 and id < 22

內存中找到根節點,確定索引定位條件id=18,找到滿足條件第一個葉節點

,順序掃描所有結果,直到終止條件滿足id >=22

3、全表掃描:select * from user_info where name = 'abc'

直接讀取葉節點頭結點, 順序掃描, 返回符合條件記錄, 到最終節點結束

4、二級索引查找:Select * from table_x where name = “d”;

id是主索引,name是二級索引。

通過二級索引查出對應主鍵,拿主鍵回表查主鍵索引得到數據, 二級索引可篩選掉大量無效記錄,提高效率。

參考文獻:1、《MySQL技術內幕》

總結

以上是生活随笔為你收集整理的mysql b 树原因_复习系列之数据库(四):MySQL为什么采用B+树作为索引结构?的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。