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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

一文介绍 Mysql 索引模型 B+ 树

發(fā)布時間:2025/3/20 数据库 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 一文介绍 Mysql 索引模型 B+ 树 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

??點擊上方?好好學(xué)java?,選擇?星標(biāo)?公眾號

重磅資訊、干貨,第一時間送達(dá) 今日推薦:后端程序員必備:書寫高質(zhì)量SQL的30條建議個人原創(chuàng)+1博客:點擊前往,查看更多 來源:https://segmentfault.com/a/1190000022192940

一、認(rèn)識二叉樹

首先,在了解 mysql 中的 B+ 樹之前,我們需要搞懂什么是二叉樹。二叉樹是一種常見的非線形數(shù)據(jù)結(jié)構(gòu),數(shù)據(jù)是以一對多的形態(tài)組織起來的,我畫了一張圖來幫助你理解:

在這里插入圖片描述

在二叉樹中,有一種比較特殊的,也是最常用的二叉樹,那就是二叉搜索樹,也叫做二叉查找樹。它最大的特點是:對于樹中的任意一個節(jié)點,假如節(jié)點值為 x,其左子樹節(jié)點的值必須小于 x,其右子樹節(jié)點的值必須大于 x,就像下圖的這幾種數(shù)據(jù)排列結(jié)構(gòu):

在這里插入圖片描述

那為什么需要使用二叉搜索樹這種結(jié)構(gòu)呢,它有什么好處嗎?我們知道,常見的線性表結(jié)構(gòu),例如鏈表,要查找一個數(shù)據(jù),必須從頭開始遍歷鏈表,在最壞的情況下,需要遍歷整個鏈表才能夠找到需要的數(shù)據(jù)。

而使用二叉搜索樹這種結(jié)構(gòu),在樹結(jié)構(gòu)趨于平衡的情況下,借助二分的思想,每次查找數(shù)據(jù)的時候,都會舍棄掉另一個子樹,所以在平均情況下,我們只需要在 O(logn)(也就是樹的高度)的時間復(fù)雜度內(nèi)就可以查找到數(shù)據(jù)。

二、為什么會選擇 B+ 樹

在了解了二叉搜索樹之后,我們就為學(xué)習(xí) B+ 樹打下了堅實的基礎(chǔ)。只不過先別著急,我們再來明確一個問題,為什么 mysql 會選擇 B+ 樹做為其索引模型呢?其他的數(shù)據(jù)結(jié)構(gòu)不行嗎?

要搞懂這個問題,我們先想想,mysql 中最常見的操作是什么?既然是數(shù)據(jù)庫,最常見的操作當(dāng)然是數(shù)據(jù)查詢了,好的,我以最常見的兩條 sql 查詢語句為例:

  • select * from T where id = 1;

  • select * from T where id > 10 and id < 20;

一個是等值查詢,一個是范圍查詢。

支持快速查詢的常見數(shù)據(jù)結(jié)構(gòu)有哈希表、平衡二叉查找樹、跳表,我們依次來看看這幾種結(jié)構(gòu)能否做為 B+ 樹的索引模型。

如果使用哈希表,雖然等值查詢非常高效,但是數(shù)據(jù)的排列是無序的,所以并不支持范圍查詢。

在這里插入圖片描述

如果使用平衡二叉查找樹,例如紅黑樹、AVL 樹等,可以在接近 O(logn) 的時間內(nèi)找到數(shù)據(jù),但是對于樹結(jié)構(gòu)來說,范圍查詢?nèi)匀皇呛艿托У?#xff0c;因為只能中序遍歷一棵樹得到一個有序的數(shù)據(jù)集,然后再依次查找。

在這里插入圖片描述

如果使用跳表,等值查詢的效率和平衡二叉查找樹差不多,并且也支持范圍查詢,例如下圖中,我們查找節(jié)點 7(紅色粗線為查找路徑),如果需要范圍查詢的話,可以順著原始鏈表依次遍歷下去,因為鏈表節(jié)點之間是有序的。

在這里插入圖片描述

這樣來說的話,跳表也是可以做為索引模型的,但 mysql 還是選擇了 B+ 樹,實際上 B+ 樹和跳表的設(shè)計思想有一些類似的地方,我們現(xiàn)在來看看 B+ 樹是什么樣子的。

三、B+ 樹模型

1. B+ 樹的優(yōu)點

對數(shù)據(jù)構(gòu)建索引,我們可以使用平衡二叉查找樹,并且稍微做一下改造,把樹的葉子節(jié)點使用鏈表串聯(lián),并且是從小到達(dá)順序排列的,那么這種結(jié)構(gòu)就能夠支持等值查詢和范圍查詢了,如下圖:

在這里插入圖片描述

當(dāng)查找到一個節(jié)點之后,我們繼續(xù)向后遍歷,就能夠?qū)崿F(xiàn)高效的范圍查詢了。值得一提的是,這里串聯(lián)葉子節(jié)點的鏈表,應(yīng)該使用雙向鏈表,方便在數(shù)據(jù)查詢后進(jìn)行升序或者降序操作。

這種結(jié)構(gòu)雖然高效,但存在一個致命的問題,那就是太消耗內(nèi)存空間了。

假如我們給 1000 萬條數(shù)據(jù)建立索引,每個節(jié)點假設(shè)大約占用 16 字節(jié)的空間,那么構(gòu)建一個索引大概就需要 150MB 內(nèi)存,實際上我們還會給很多張表的很多字段建立索引,這樣的話內(nèi)存空間消耗還是太大了。

所以我們可以根據(jù)空間換時間的思想,使用磁盤來代替內(nèi)存,磁盤是一種慢速的存儲設(shè)備,造價也比內(nèi)存低廉很多,因此我們可以將數(shù)據(jù)存儲到磁盤上,只不過這樣數(shù)據(jù)查詢的速度就會慢一些了。

針對這種數(shù)據(jù)存儲的方式,如果我們還是用上述的那種二叉樹結(jié)構(gòu)的話,每訪問一層節(jié)點就對應(yīng)著一次磁盤 IO,那這樣的查詢速度還是太慢了。因此我們可以改造一下上圖中的這個結(jié)構(gòu),將二叉變成 n 叉,這樣每一層節(jié)點存儲的數(shù)據(jù)變多了,樹的高度也降低了,訪問磁盤的次數(shù)變少了,相應(yīng)的查詢性能就能夠得到提升。

比如存儲 30 個數(shù)據(jù),構(gòu)建二叉樹的高度是 5,而 5 叉樹的高度僅為 3:

在這里插入圖片描述

如果數(shù)據(jù)量再大一點,就更能看出差別了,比如我們構(gòu)建的是 100 叉樹,那么存儲 1 億個數(shù)據(jù),樹的高度也只是 5 ,這樣的話磁盤 IO 的操作次數(shù)就被大大的降低了。

那么在實際的應(yīng)用中,到底應(yīng)該構(gòu)建多少叉樹呢?是不是樹的節(jié)點越多,即 n 越大越好?我們知道,操作系統(tǒng)對磁盤的訪問是以頁為單位讀取的,每頁的大小通常是 4KB,也就是說我們只需要將 n 叉樹的每個節(jié)點存儲為一頁大小左右,這樣每次訪問都能夠整頁讀取,不會進(jìn)行多余的磁盤 IO 操作。

假如每頁的大小可以存儲 3 個數(shù)據(jù),那么最終的 B+ 樹結(jié)構(gòu)就是這個樣子:

在這里插入圖片描述

2. B+ 樹的缺點

這樣來看的話,似乎 B+ 樹已經(jīng)比較完美的解決了數(shù)據(jù)索引的問題,但是,天下沒有免費的午餐,B+ 樹對查詢操作有了很大的提升,但同時也降低了數(shù)據(jù)插入和刪除的效率。

這個問題似乎不難理解,當(dāng)我們不斷插入數(shù)據(jù)的時候,B+ 樹中的節(jié)點肯定會越來越多,直到大于了頁大小,這時,為了維護(hù)查詢的效率,不產(chǎn)生多余的 IO 操作,我們不得不進(jìn)行節(jié)點的重構(gòu)。

假如葉子節(jié)點的數(shù)量是 m,當(dāng)節(jié)點數(shù)量大于 m 的時候,該節(jié)點就會分裂,從葉子節(jié)點的最中間的那個節(jié)點,讓其成為父節(jié)點,節(jié)點左右的值,分別成為新的左右子節(jié)點;如果上一層又超過了限制,則繼續(xù)向上進(jìn)行分裂,直到影響到根節(jié)點,參照下面的圖就很容易理解了:

在這里插入圖片描述

刪除也是類似的道理,當(dāng)葉子節(jié)點過少,例如少于 m / 2 的時候,就可以將節(jié)點合并至旁邊的兄弟節(jié)點。你可以自己參照插入的思路,想想刪除是怎么進(jìn)行節(jié)點重構(gòu)的。

好了,這篇文章講述了 mysql 的索引模型 B+ 樹,首先需要了解一下二叉樹,這是學(xué)習(xí) B+ 樹的前提,然后我以兩個最常見的查詢 sql,向你描述了為什么其他的常見數(shù)據(jù)結(jié)構(gòu)不適合用來做索引,然后由此引出了 B+ 樹。

根據(jù)數(shù)據(jù)查詢和存儲的特點,對平衡二叉樹逐步改造成了 B+ 樹,B+ 樹對數(shù)據(jù)查詢起到了很好的作用,但是它也帶有副作用,那就是對插入刪除操作有影響,于是需要進(jìn)行節(jié)點的重構(gòu)。

為了幫助你更深刻的理解并學(xué)習(xí) B+ 樹,這里貼一下其他關(guān)于 B+ 樹的優(yōu)秀文章:

https://zh.wikipedia.org/wiki/B%2B%E6%A0%91https://zhuanlan.zhihu.com/p/27700617https://www.cnblogs.com/nullzx/p/8729425.html

總結(jié)

以上是生活随笔為你收集整理的一文介绍 Mysql 索引模型 B+ 树的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。