偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

為什么MySQL的常用引擎都默認(rèn)使用B+樹(shù)作為索引?

數(shù)據(jù)庫(kù) MySQL
相信大家對(duì)為什么MySQL的常用引擎都默認(rèn)使用B+樹(shù)作為索引已經(jīng)有了初步的認(rèn)知。我們只要牢記一點(diǎn):索引是為了減少磁盤(pán)io提高查詢性能而存在的。

 [[319158]]

一、前言

為了講清楚這個(gè)問(wèn)題,阿粉先帶大家了解一下什么是索引。

 

 

 

[[319159]]

 

我記得剛剛學(xué)習(xí)數(shù)據(jù)庫(kù)的時(shí)候,老師喜歡用書(shū)本的目錄來(lái)類比數(shù)據(jù)庫(kù)的索引,并告訴我們索引能夠像目錄一樣,讓我們更快地找到想要找到的數(shù)據(jù)。

如果是第一次接觸索引,這個(gè)比喻能夠讓我們有一個(gè)直觀的印象。但是當(dāng)深入去學(xué)習(xí)索引的時(shí)候,我們不能繼續(xù)持有索引即目錄的思想,我們要跳出來(lái)去思考索引的本質(zhì)是什么。

 

 

 

[[319160]]

 

二、索引的本質(zhì)

在沒(méi)有索引的情況下,我們查找數(shù)據(jù)只能按照從頭到尾的順序逐行查找,每查找一行數(shù)據(jù),意味著我們要到到磁盤(pán)相應(yīng)的位置去讀取一條數(shù)據(jù)。

如果把查詢一條數(shù)據(jù)分為到磁盤(pán)中查詢和比對(duì)查詢條件兩步的話,到磁盤(pán)中查詢的時(shí)間會(huì)遠(yuǎn)遠(yuǎn)大于比對(duì)查詢條件的時(shí)間,這意味著在一次查詢中,磁盤(pán)io占用了大部分的時(shí)間。更進(jìn)一步地說(shuō),一次查詢的效率取絕于磁盤(pán)io的次數(shù),如果我們能夠在一次查詢中盡可能地降低磁盤(pán)io的次數(shù),那么我們就能加快查詢的速度。

 

 

 

[[319161]]

 

在知道了減少磁盤(pán)io能加快查詢速度后,我們就要聚焦于如何減少磁盤(pán)io。如果按照原表逐行查詢的話,n條數(shù)據(jù)就要查詢n次,也就是O(N)的時(shí)間復(fù)雜度,為了減少磁盤(pán)io的次數(shù),我們必須用一種查詢時(shí)間復(fù)雜度更低的數(shù)據(jù)結(jié)構(gòu)來(lái)保存數(shù)據(jù)。

這種查詢時(shí)間復(fù)雜度低的數(shù)據(jù)結(jié)構(gòu),我們稱之為索引。所以通俗來(lái)說(shuō),索引其實(shí)就是某種數(shù)據(jù)結(jié)構(gòu),能充當(dāng)索引的數(shù)據(jù)結(jié)構(gòu)是多種多樣的。

三、索引的選擇

既然索引是一種便于查詢的數(shù)據(jù)結(jié)構(gòu),如果大家對(duì)數(shù)據(jù)結(jié)構(gòu)有一定了解的話,大概率會(huì)首選樹(shù)型結(jié)構(gòu)。畢竟樹(shù)型結(jié)構(gòu)普遍有著O(logN)的查詢時(shí)間復(fù)雜度,而且插入刪除數(shù)據(jù)的性能也比較平均。(可能你會(huì)說(shuō)數(shù)組,哈希表的查詢速度也很高啊,這個(gè)后面也會(huì)分析)

 

 

 

[[319162]]

 

雖然我們都已經(jīng)知道Mysql中最常用的引擎像InnoDB和MyISAM,最終都選擇了B+樹(shù)作為索引,但是這里我還是打算從最常見(jiàn)的二叉樹(shù)開(kāi)始講起,推導(dǎo)一下為什么最終選擇了B+樹(shù)作為索引,并比較一下幾種樹(shù)型結(jié)構(gòu)在充當(dāng)索引時(shí)的優(yōu)劣。

二叉樹(shù)

最普通的二叉樹(shù)的問(wèn)題在于他不能保證O(logN)的查詢時(shí)間復(fù)雜度,我們看下面的圖:

 

 

 

 

由于插入的元素逐漸增大,元素始終在右邊進(jìn)行插入,好好的一棵二叉樹(shù)最終變成了一條“鏈表”。在這種極端的情況下,二叉樹(shù)的查詢時(shí)間復(fù)雜度不再是O(logN),而是退化為O(N),這樣顯然不符合索引的要求。

平衡二叉樹(shù)(紅黑樹(shù))

像紅黑樹(shù)這樣的平衡二叉樹(shù),無(wú)論如何插入元素,他都可以通過(guò)一些旋轉(zhuǎn)的方法調(diào)整樹(shù)的高度,使得整棵樹(shù)的查詢效率維持在O(logN),如下圖所示:

 

 

 

 

這么來(lái)說(shuō)他已經(jīng)符合了成為索引的必備條件,但是最終沒(méi)有選擇他作為索引說(shuō)明還有不足的地方。仔細(xì)看看可以發(fā)現(xiàn)平衡二叉樹(shù)的每個(gè)節(jié)點(diǎn)只有兩個(gè)孩子節(jié)點(diǎn),如果一張表的數(shù)據(jù)量特別大,整棵樹(shù)的高度也會(huì)隨之上升。一個(gè)千萬(wàn)級(jí)別的表如果用平衡二叉樹(shù)作為索引的話,樹(shù)高將會(huì)達(dá)到二十多層。這也就意味著做一次查詢需要二十多次磁盤(pán)io,這是一個(gè)不小的開(kāi)銷。

那么有沒(méi)有能在大數(shù)據(jù)量的情況下,還能保持一個(gè)較小樹(shù)高的樹(shù)型結(jié)構(gòu)呢?

B樹(shù)和B+樹(shù)

答案就是B樹(shù)。上面我們說(shuō)到了平衡二叉樹(shù)的瓶頸在于一個(gè)節(jié)點(diǎn)只有兩個(gè)孩子節(jié)點(diǎn),而B(niǎo)樹(shù)一個(gè)節(jié)點(diǎn)可以存放N個(gè)孩子節(jié)點(diǎn),這就完美解決了樹(shù)高的問(wèn)題,我們可以把B樹(shù)稱為平衡多叉樹(shù),B樹(shù)作為索引如下圖所示:

 

 

 

 

圖片來(lái)源網(wǎng)絡(luò)

但是以B樹(shù)的結(jié)構(gòu)作為索引仍有可以優(yōu)化的地方,我們先看看最終的B+樹(shù),再仔細(xì)分析B+樹(shù)在B樹(shù)的基礎(chǔ)上作了哪些改進(jìn),為什么B+樹(shù)最終能夠勝任索引的工作:

 

 

 

 

圖片來(lái)源網(wǎng)絡(luò)

從圖片中可以看到B+樹(shù)同樣是一棵多差平衡樹(shù),和B樹(shù)一樣很好地解決了樹(shù)高的問(wèn)題。

改進(jìn)點(diǎn)一:

但仔細(xì)看可以發(fā)現(xiàn),B樹(shù)的節(jié)點(diǎn)中既存儲(chǔ)索引,也存儲(chǔ)表對(duì)應(yīng)的數(shù)據(jù);而B(niǎo)+樹(shù)的非葉子節(jié)點(diǎn)是不存儲(chǔ)數(shù)據(jù)的,只存儲(chǔ)索引,數(shù)據(jù)全部存儲(chǔ)在葉子節(jié)點(diǎn)上。

為什么要做這樣的改進(jìn)?我們做一次算術(shù)就知道了。

假設(shè)樹(shù)高為2,主鍵ID為bigint類型,長(zhǎng)度為8字節(jié),節(jié)點(diǎn)指針為6字節(jié),一行數(shù)據(jù)記錄的大小為1k,一次io操作能獲得一頁(yè)16k的數(shù)據(jù)。

在索引為B+樹(shù)的情況下,根節(jié)點(diǎn)能存儲(chǔ):16k / (6 + 8) = 1170 條索引指針;到了第一層,一共能指向 1170 * 1170 = 1368900 條索引指針;到了最底一層葉子節(jié)點(diǎn),一個(gè)節(jié)點(diǎn)能存儲(chǔ)16k / 1k = 16 條記錄,一共能存儲(chǔ) 1170 * 1170 * 16 = 21902400 條記錄

在B樹(shù)的情況下,由于非葉子節(jié)點(diǎn)使用了大量空間存儲(chǔ)數(shù)據(jù),存放的索引指針肯定就少,最終整棵樹(shù)如果想要存儲(chǔ)和B+樹(shù)一樣多的數(shù)據(jù)就必須要增加樹(shù)高,這樣一來(lái)就增加了磁盤(pán)io,所以說(shuō)B+樹(shù)作為索引的性能比B樹(shù)高。

改進(jìn)點(diǎn)二:

葉子節(jié)點(diǎn)之間使用指針連接,提高區(qū)間訪問(wèn)效率。如果我們要進(jìn)行范圍查詢,可以輕松通過(guò)B+樹(shù)葉子節(jié)點(diǎn)之間的指針進(jìn)行遍歷,減少了不必要的磁盤(pán)io。

總結(jié)

看到這里,相信大家對(duì)為什么Mysql的常用引擎都默認(rèn)使用B+樹(shù)作為索引已經(jīng)有了初步的認(rèn)知。我們只要牢記一點(diǎn):索引是為了減少磁盤(pán)io提高查詢性能而存在的。

 

 

 

[[319167]]

 

最后回應(yīng)一下為什么不常用哈希表和數(shù)組作為索引

哈希表雖然單一個(gè)值的查詢效率很高,但是撐不住范圍查詢,哪個(gè)公司的業(yè)務(wù)還沒(méi)個(gè)范圍查詢呢?

而數(shù)組雖然查詢的效率高,但是增加和刪除的效率低,由于記錄在增加和刪除的時(shí)候索引也得跟著維護(hù),這會(huì)導(dǎo)致大數(shù)據(jù)量的情況下,增加或刪除一條記錄效率較低。

 

責(zé)任編輯:武曉燕 來(lái)源: Java極客技術(shù)
相關(guān)推薦

2022-03-28 08:24:52

MySQL聚簇索引非聚簇索引

2024-05-22 09:01:53

InnoDBB+索引

2019-09-24 09:33:53

MySQLB+樹(shù)InnoDB

2022-04-16 14:20:29

MySQL數(shù)據(jù)庫(kù)

2019-01-29 19:43:10

MySQL索引數(shù)據(jù)庫(kù)

2019-03-14 09:51:50

MySQL存儲(chǔ)邏輯架構(gòu)

2020-04-01 18:08:57

MySQL B-樹(shù)B+樹(shù)

2019-08-29 10:46:22

MySQL索引數(shù)據(jù)庫(kù)

2020-02-12 19:01:22

索引B-樹(shù)B+樹(shù)

2021-02-16 16:38:41

MySQLB+樹(shù)索引

2021-07-04 15:16:14

索引B+數(shù)據(jù)庫(kù)

2021-05-19 09:51:31

MySQL-B+樹(shù)數(shù)據(jù)

2015-04-21 13:09:01

B+樹(shù)MySQL索引結(jié)構(gòu)

2023-06-06 09:03:06

InnodbMySQL

2021-11-18 23:08:53

MySQLSQL索引

2019-12-31 09:33:03

MongoDBB 樹(shù)NoSQL

2021-04-19 10:03:33

MongoDbB 樹(shù) B+ 樹(shù)

2019-11-05 14:06:07

MySQLB+索引

2019-11-04 15:00:50

MySQL索引B+樹(shù)

2020-03-18 09:33:47

數(shù)據(jù)庫(kù)程序員數(shù)組
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)