這篇文章給大家介紹MongoDB中使用B樹(shù)索引的原因是什么,內(nèi)容非常詳細(xì),感興趣的小伙伴們可以參考借鑒,希望對(duì)大家能有所幫助。
為開(kāi)平等地區(qū)用戶(hù)提供了全套網(wǎng)頁(yè)設(shè)計(jì)制作服務(wù),及開(kāi)平網(wǎng)站建設(shè)行業(yè)解決方案。主營(yíng)業(yè)務(wù)為成都做網(wǎng)站、網(wǎng)站建設(shè)、外貿(mào)營(yíng)銷(xiāo)網(wǎng)站建設(shè)、開(kāi)平網(wǎng)站設(shè)計(jì),以傳統(tǒng)方式定制建設(shè)網(wǎng)站,并提供域名空間備案等一條龍服務(wù),秉承以專(zhuān)業(yè)、用心的態(tài)度為用戶(hù)提供真誠(chéng)的服務(wù)。我們深信只要達(dá)到每一位用戶(hù)的要求,就會(huì)得到認(rèn)可,從而選擇與我們長(zhǎng)期合作。這樣,我們也可以走得更遠(yuǎn)!
B樹(shù)和B+樹(shù)
開(kāi)頭,我們先回憶一下,B樹(shù)和B+樹(shù)的結(jié)構(gòu)以及特點(diǎn)。
樹(shù)內(nèi)的每個(gè)節(jié)點(diǎn)都存儲(chǔ)數(shù)據(jù);
葉子節(jié)點(diǎn)之間無(wú)指針相鄰。
注意一下B樹(shù)的兩個(gè)明顯特點(diǎn):
數(shù)據(jù)只出現(xiàn)在葉子節(jié)點(diǎn);
所有葉子節(jié)點(diǎn)增加了一個(gè)鏈指針。
針對(duì)上面的B+樹(shù)和B樹(shù)的特點(diǎn),我們做一個(gè)總結(jié):
(1)B樹(shù)的樹(shù)內(nèi)存儲(chǔ)數(shù)據(jù),因此查詢(xún)單條數(shù)據(jù)的時(shí)候,B樹(shù)的查詢(xún)效率不固定,最好的情況是O(1)。我們可以認(rèn)為在做單一數(shù)據(jù)查詢(xún)的時(shí)候,使用B樹(shù)平均性能更好。但是,由于B樹(shù)中各節(jié)點(diǎn)之間沒(méi)有指針相鄰,因此B樹(shù)不適合做一些數(shù)據(jù)遍歷操作。
(2) B+樹(shù)的數(shù)據(jù)只出現(xiàn)在葉子節(jié)點(diǎn)上,因此在查詢(xún)單條數(shù)據(jù)的時(shí)候,查詢(xún)速度非常穩(wěn)定。因此,在做單一數(shù)據(jù)的查詢(xún)上,其平均性能并不如B樹(shù)。但是,B+樹(shù)的葉子節(jié)點(diǎn)上有指針進(jìn)行相連,因此在做數(shù)據(jù)遍歷的時(shí)候,只需要對(duì)葉子節(jié)點(diǎn)進(jìn)行遍歷即可,這個(gè)特性使得B+樹(shù)非常適合做范圍查詢(xún)。
因此,我們可以做一個(gè)推論:沒(méi)準(zhǔn)是MySQL中數(shù)據(jù)遍歷操作比較多,所以用B+樹(shù)作為索引結(jié)構(gòu)。而Mongodb是做單一查詢(xún)比較多,數(shù)據(jù)遍歷操作比較少,所以用B樹(shù)作為索引結(jié)構(gòu)。
那么為什么Mysql做數(shù)據(jù)遍歷操作多?而Mongodb做數(shù)據(jù)遍歷操作少呢?
因?yàn)镸ysql是關(guān)系型數(shù)據(jù)庫(kù),而Mongodb是非關(guān)系型數(shù)據(jù)。
那為什么關(guān)系型數(shù)據(jù)庫(kù),做數(shù)據(jù)遍歷操作多?
而非關(guān)系型數(shù)據(jù)庫(kù),做數(shù)據(jù)遍歷操作少呢?
關(guān)系型VS非關(guān)系型
假設(shè),我們此時(shí)有兩個(gè)邏輯實(shí)體:學(xué)生(Student)和班級(jí)(Class),這兩個(gè)邏輯實(shí)體之間是一對(duì)多的關(guān)系。畢竟一個(gè)班級(jí)有多個(gè)學(xué)生,一個(gè)學(xué)生只能屬于一個(gè)班級(jí)。
關(guān)系型數(shù)據(jù)庫(kù)
我們?cè)陉P(guān)系型數(shù)據(jù)庫(kù)中,考慮的是用幾張表來(lái)表示這二者之間的實(shí)體關(guān)系。常見(jiàn)的無(wú)外乎是,一對(duì)一關(guān)系,用一張表就行。一對(duì)多關(guān)系,用兩張表。多對(duì)多關(guān)系,用三張表。
那我們,此時(shí)要查 cname 為 1班 的班級(jí),有多少學(xué)生怎么辦?
假設(shè) cname 這列,我們建了索引!
執(zhí)行SQL,如下所示!
SELECT *
FROM t_student t1, (
SELECT cid
FROM t_class
WHERE cname = '1班'
) t2
WHERE t1.cid = t2.cid
而這,就涉及到了數(shù)據(jù)遍歷操作!
因?yàn)榈沧鲞@種關(guān)聯(lián)查詢(xún),你躲不開(kāi)join操作的!既然涉及到了join操作,無(wú)外乎從一個(gè)表中取一個(gè)數(shù)據(jù),去另一個(gè)表中逐行匹配,如果索引結(jié)構(gòu)是B+樹(shù),葉子節(jié)點(diǎn)上是有指針的,能夠極大的提高這種一行一行的匹配速度!
有的人或許會(huì)抬杠說(shuō),如果我先執(zhí)行:
SELECT cid
FROM t_class
WHERE cname = '1班'
獲得cid后,再去循環(huán)執(zhí)行:
SELECT *
FROM t_student
WHERE cid = ...
就可以避開(kāi)join操作呀?
對(duì)此,我想說(shuō)。你確實(shí)避開(kāi)了join操作,但是你數(shù)據(jù)遍歷操作還是沒(méi)避開(kāi)。你還是需要在student的這張表的葉子節(jié)點(diǎn)上,一遍又一遍的遍歷!
那在非關(guān)系型數(shù)據(jù)庫(kù)中,我們?nèi)绾尾樵?xún) cname 為 1班 的班級(jí),有多少學(xué)生?
非關(guān)系型數(shù)據(jù)庫(kù)
執(zhí)行兩次查詢(xún)?nèi)カ@得結(jié)果!一次去class集合查,獲得id后再去student集合查。
確實(shí),這么設(shè)計(jì)是可以的,我沒(méi)說(shuō)不行。只是不符合非關(guān)系型數(shù)據(jù)庫(kù)的設(shè)計(jì)初衷。在MongoDB中,根本不推薦這么設(shè)計(jì)。雖然,Mongodb中有一個(gè)$lookup操作,可以做join查詢(xún)。但是理想情況下,這個(gè)$lookup操作應(yīng)該不會(huì)經(jīng)常使用,如果你需要經(jīng)常使用它,那么你就使用了錯(cuò)誤的數(shù)據(jù)存儲(chǔ)了(數(shù)據(jù)庫(kù)):如果你有相關(guān)聯(lián)的數(shù)據(jù),應(yīng)該使用關(guān)系型數(shù)據(jù)庫(kù)(SQL)。
假設(shè) name 這列,我們建了索引!
我只需執(zhí)行一次語(yǔ)句:
db.class.find( { name: '1班' } )
這樣就能查詢(xún)出自己想要的結(jié)果。
而這,就是一種單一數(shù)據(jù)查詢(xún)!畢竟你不需要去逐行匹配,不涉及遍歷操作,幸運(yùn)的情況下,有可能一次IO就能夠得到你想要的結(jié)果。
因此,由于關(guān)系型數(shù)據(jù)庫(kù)和非關(guān)系型數(shù)據(jù)的設(shè)計(jì)方式上的不同。導(dǎo)致在關(guān)系型數(shù)據(jù)中,遍歷操作比較常見(jiàn),因此采用B+樹(shù)作為索引,比較合適。而在非關(guān)系型數(shù)據(jù)庫(kù)中,單一查詢(xún)比較常見(jiàn),因此采用B樹(shù)作為索引,比較合適。
目前面試套路有如下幾種:
套路一
你簡(jiǎn)歷寫(xiě)了mysql,沒(méi)寫(xiě)mongodb!
面試官:"說(shuō)說(shuō)mysql索引結(jié)構(gòu)?"
我:"巴拉巴拉"
面試官:"知道為什么用B+樹(shù),不用B樹(shù)么?"
這個(gè)時(shí)候正常的面試者就蒙了,會(huì)把B樹(shù)的缺點(diǎn)噴一通!于是乎下一問(wèn)就是。
面試官:"其實(shí)一些非關(guān)系型數(shù)據(jù)庫(kù),如mongodb用的就是B樹(shù),你知道原因么?"
然后你就回去等通知了!
套路二
你簡(jiǎn)歷寫(xiě)了mysql,也寫(xiě)了mongodb!
這種情況更完美!
面試官:"說(shuō)說(shuō)mysql索引結(jié)構(gòu)?"
我:"巴拉巴拉"
面試官:"你簡(jiǎn)歷寫(xiě)了Mongodb,有了解過(guò)他的索引結(jié)構(gòu)么?"
我:"巴拉巴拉"
面試官:"為什么Mongodb索引用B樹(shù),而Mysql用B+樹(shù)?"
然后你就回去等通知了!
套路三
你簡(jiǎn)歷既沒(méi)寫(xiě)mysql,沒(méi)寫(xiě)mongodb!
面試官;"如果你來(lái)設(shè)計(jì)數(shù)據(jù)庫(kù),你會(huì)對(duì)他的索引用什么數(shù)據(jù)結(jié)構(gòu)?"
我:"首先不考慮紅黑樹(shù)這類(lèi),巴拉巴拉…應(yīng)該會(huì)用B樹(shù)或者B+樹(shù)。"
面試官;“如果我要設(shè)計(jì)一個(gè)像Mongodb那樣的非關(guān)系型數(shù)據(jù)庫(kù),我要用什么數(shù)據(jù)結(jié)構(gòu)當(dāng)索引比較合適?”
關(guān)于Mongodb中使用B樹(shù)索引的原因是什么就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到。