真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

MySQL中的索引有哪些類(lèi)型或者種類(lèi)

本文主要給大家簡(jiǎn)單講講MySQL中的索引有哪些類(lèi)型或者種類(lèi),相關(guān)專(zhuān)業(yè)術(shù)語(yǔ)大家可以上網(wǎng)查查或者找一些相關(guān)書(shū)籍補(bǔ)充一下,這里就不涉獵了,我們就直奔主題吧,希望MySQL中的索引有哪些類(lèi)型或者種類(lèi)這篇文章可以給大家?guī)?lái)一些實(shí)際幫助。

創(chuàng)新互聯(lián)專(zhuān)注于沁水網(wǎng)站建設(shè)服務(wù)及定制,我們擁有豐富的企業(yè)做網(wǎng)站經(jīng)驗(yàn)。 熱誠(chéng)為您提供沁水營(yíng)銷(xiāo)型網(wǎng)站建設(shè),沁水網(wǎng)站制作、沁水網(wǎng)頁(yè)設(shè)計(jì)、沁水網(wǎng)站官網(wǎng)定制、微信平臺(tái)小程序開(kāi)發(fā)服務(wù),打造沁水網(wǎng)絡(luò)公司原創(chuàng)品牌,更為您提供沁水網(wǎng)站排名全網(wǎng)營(yíng)銷(xiāo)落地服務(wù)。

                                                           MySQL中的索引有哪些類(lèi)型或者種類(lèi)

什么是索引

索引是一種數(shù)據(jù)結(jié)構(gòu),其作用就是用來(lái)提高數(shù)據(jù)查詢(xún)效率。比較常用的比喻就是將其類(lèi)比為書(shū)籍的目錄。通過(guò)目錄可以精確的找到某一章節(jié)的內(nèi)容所在頁(yè)。

在數(shù)據(jù)量較小的時(shí)候使用索引其實(shí)也沒(méi)有什么意義,即使沒(méi)有索引需要一條一條遍歷數(shù)據(jù)對(duì)于計(jì)算機(jī)來(lái)說(shuō)也并不需要太多時(shí)間。而一旦數(shù)據(jù)量較大,要保證我們能正常的對(duì)外提供服務(wù),保證用戶(hù)使用體驗(yàn)?zāi)敲此饕褪潜匾牧恕?/p>

索引類(lèi)型

索引是一種數(shù)據(jù)結(jié)構(gòu),為了應(yīng)對(duì)不同的場(chǎng)景會(huì)有多種實(shí)現(xiàn)。在MySQL中主要就是Hash索引和B+Tree。

Hash索引

hash相信大家應(yīng)該都很熟悉,hash是一種key-value形式的數(shù)據(jù)結(jié)構(gòu)。實(shí)現(xiàn)一般是數(shù)組+鏈表的結(jié)構(gòu),通過(guò)hash函數(shù)計(jì)算出key在數(shù)組中的位置,然后如果出現(xiàn)hash沖突就通過(guò)鏈表來(lái)解決(拉鏈法)。當(dāng)然還有其他的解決hash沖突的方法。hash這種數(shù)據(jù)結(jié)構(gòu)是很常用的,比如我們系統(tǒng)使用HashMap來(lái)構(gòu)建熱點(diǎn)數(shù)據(jù)緩存,存取效率很好。

hash結(jié)構(gòu)存數(shù)據(jù)首先通過(guò)計(jì)算key的hash值來(lái)確定其在數(shù)組中的位置,如果有沖突就在該數(shù)組位置建一個(gè)鏈表。這樣很明顯有幾個(gè)問(wèn)題:

即使是具有相同特征的key計(jì)算出來(lái)的位置可能相隔很遠(yuǎn),連續(xù)查詢(xún)效率低下。即不支持范圍查詢(xún)。

hash索引存儲(chǔ)的事計(jì)算得到的hash值和行指針,而不存儲(chǔ)具體的行值,所以通過(guò)hash索引查詢(xún)數(shù)據(jù)需要進(jìn)行兩次查詢(xún)(首先查詢(xún)行的位置,然后找到具體的數(shù)據(jù))

hash索引查詢(xún)數(shù)據(jù)的前提就是計(jì)算hash值,也就是要求key為一個(gè)能準(zhǔn)確指向一條數(shù)據(jù)的key,所以對(duì)于like等一類(lèi)的匹配查詢(xún)是不支持的。

所以我們可以知道的是hash索引適用于快速選取某一行的數(shù)據(jù)。

B+Tree結(jié)構(gòu)

從名字上看這明顯是一種樹(shù)結(jié)構(gòu),在大學(xué)期間數(shù)據(jù)結(jié)構(gòu)的課本上樹(shù)結(jié)構(gòu)是必講的。樹(shù)結(jié)構(gòu)是一種特別重要的數(shù)據(jù)結(jié)構(gòu),在很多地方都會(huì)使用到。

上面我們說(shuō)到hash索引無(wú)法進(jìn)行范圍查詢(xún),在樹(shù)結(jié)構(gòu)中也有一種方便進(jìn)行有序查詢(xún)的結(jié)構(gòu)--二叉搜索樹(shù)。二叉搜索樹(shù)的結(jié)構(gòu)中要求父節(jié)點(diǎn)的值大于左孩子節(jié)點(diǎn)并且小于右孩子節(jié)點(diǎn),如下圖:

MySQL中的索引有哪些類(lèi)型或者種類(lèi)

上圖中二叉樹(shù)的查詢(xún)的時(shí)間復(fù)雜度為O(log(n)),當(dāng)然要保證O(log(n))的時(shí)間復(fù)雜度就需要保證二叉樹(shù)時(shí)刻保持平衡。

而在MySQL索引中雖然也使用了樹(shù)結(jié)構(gòu),但是并不是使用的二叉樹(shù)。因?yàn)樵跀?shù)據(jù)庫(kù)中數(shù)據(jù)最終都是存放在磁盤(pán)上的,而如果樹(shù)的節(jié)點(diǎn)過(guò)多的話(huà),那么在節(jié)點(diǎn)之間轉(zhuǎn)移會(huì)花費(fèi)較多的時(shí)間。在MySQL的實(shí)現(xiàn)中選擇將更多內(nèi)容放在同一個(gè)節(jié)點(diǎn),對(duì)同一個(gè)節(jié)點(diǎn)的操作轉(zhuǎn)入在內(nèi)存中完成,減少在外存中節(jié)點(diǎn)之間轉(zhuǎn)移的次數(shù),以達(dá)到提高效率的目的。這就是B+Tree,在B+Tree的實(shí)現(xiàn)中一個(gè)三層的樹(shù)結(jié)構(gòu)就基本上可以滿(mǎn)足我們幾乎所有的需求了。

相關(guān)推薦:《mysql數(shù)據(jù)庫(kù)知識(shí)學(xué)習(xí)》

B-Tree

要了解B+Tree首先就得了解B-Tree,B-Tree是一種平衡樹(shù),這里的B指的是Balance而不是Binary,更確切的說(shuō)B-Tree是一種多路平衡搜索樹(shù)。

多路平衡搜索樹(shù)如下圖:

MySQL中的索引有哪些類(lèi)型或者種類(lèi)

這是一種2-3樹(shù),意思就是每個(gè)節(jié)點(diǎn)存有兩個(gè)值,同時(shí)每個(gè)節(jié)點(diǎn)分支數(shù)為3,從上圖中可以看出來(lái)著中結(jié)構(gòu)很適合查詢(xún)數(shù)據(jù)。每個(gè)節(jié)點(diǎn)的左子樹(shù)的值都是小于當(dāng)前節(jié)點(diǎn)中最小的值,中間的子樹(shù)的值全都是在當(dāng)前節(jié)點(diǎn)兩個(gè)值的中間,而右子樹(shù)的值全都大于當(dāng)前節(jié)點(diǎn)的最大值。

比如我們要查找24這個(gè)值:

(1)首先從根節(jié)點(diǎn)判斷24在根節(jié)點(diǎn)(15,25)之間,所以左右子樹(shù)排除,從中間查找。

(2)然后找到中間子樹(shù)的根節(jié)點(diǎn)(18,22),比較發(fā)現(xiàn)24大于該節(jié)點(diǎn)最大值,排除左子樹(shù)和中間子樹(shù)。

(3)找到右子樹(shù),判斷節(jié)點(diǎn)大值剛好等于24,查詢(xún)結(jié)束。

基于上面的流程可以總結(jié)B樹(shù)的搜索:

(1)從根結(jié)點(diǎn)開(kāi)始,對(duì)結(jié)點(diǎn)內(nèi)的關(guān)鍵字(有序)序列進(jìn)行二分查找。

(2)如果命中則結(jié)束,否則進(jìn)入查詢(xún)關(guān)鍵字所屬范圍的子結(jié)點(diǎn);

(3)重復(fù)上面的流程,直到所對(duì)應(yīng)的子節(jié)點(diǎn)為空,或已經(jīng)是葉子結(jié)點(diǎn);

可以看出其搜索性能相當(dāng)于在關(guān)鍵字集合內(nèi)做一次二分查找。從這里看來(lái)好像B-Tree沒(méi)有什么問(wèn)題,但是需要注意到的是在B-Tree中每一個(gè)節(jié)點(diǎn)都是存儲(chǔ)索引關(guān)鍵字以及其代表的具體行數(shù)據(jù)。而在MySQL中數(shù)據(jù)庫(kù)加載數(shù)據(jù)是以頁(yè)為單位加載,每一頁(yè)的大小是固定的(默認(rèn)16k)。如果每一個(gè)節(jié)點(diǎn)都存儲(chǔ)所有的值,那么一頁(yè)中能存下的節(jié)點(diǎn)就會(huì)很少,一次查詢(xún)可能就會(huì)進(jìn)行多次從內(nèi)存中去加載數(shù)據(jù),導(dǎo)致性能降低。

B+Tree

B+Tree是對(duì)B-Tree的一個(gè)變種,讓其更加適應(yīng)于進(jìn)行外部存儲(chǔ)文件索引。

兩者之前最大的不同就在于B-Tree的每個(gè)節(jié)點(diǎn)都存儲(chǔ)所有的數(shù)據(jù),而B(niǎo)+Tree需要存儲(chǔ)的數(shù)據(jù)都在葉子節(jié)點(diǎn)上,并且增加了順序訪問(wèn)指針,每個(gè)葉子節(jié)點(diǎn)都有指向下一個(gè)相鄰的葉子節(jié)點(diǎn)的地址。這樣的結(jié)構(gòu)保證了在一個(gè)內(nèi)存頁(yè)中可以存下更多的索引節(jié)點(diǎn),并且更加適合進(jìn)行范圍查詢(xún)。

索引

因?yàn)榇鎯?chǔ)引擎負(fù)責(zé)實(shí)現(xiàn)索引,所以接下來(lái)討論索引都是基于MySQL的InnoDB引擎。

聚簇索引

聚簇的意思是表示數(shù)據(jù)行和相鄰的鍵值聚簇的存儲(chǔ)在一起。一些數(shù)據(jù)庫(kù)允許選擇具體的某一個(gè)索引作為聚簇索引,而在InnoDB的實(shí)現(xiàn)中直接將主鍵索引指定為聚簇索引。如果沒(méi)有定義主鍵,InnoDB 會(huì)選擇一個(gè)唯一的非空索引來(lái)代替主鍵索引。如果同樣沒(méi)有定義這樣的索引,InnoDB會(huì)隱式定義一個(gè)主鍵來(lái)作為聚簇索引(row_id)。

聚簇索引實(shí)例如圖:

MySQL中的索引有哪些類(lèi)型或者種類(lèi)

非聚簇索引索引

在InnoDB中除主鍵索引外其他都是非聚簇索引,所以也叫非主鍵索引。非主鍵索引的葉節(jié)點(diǎn)并不是存儲(chǔ)一行的值,而是存儲(chǔ)具體行的主鍵值。不滿(mǎn)足聚簇的定義。

非聚簇索引實(shí)例如圖:

MySQL中的索引有哪些類(lèi)型或者種類(lèi)

聚簇索引和非聚簇索引在查詢(xún)時(shí)的差異

由上面的兩種索引實(shí)例圖就可以看出來(lái),在查詢(xún)時(shí)如果是通過(guò)主鍵索引查詢(xún)的話(huà)直接查詢(xún)到數(shù)據(jù)行然后返回。但是如果是通過(guò)非主鍵索引查詢(xún)的話(huà)首先需要通過(guò)該索引確定主鍵,然后通過(guò)得到的主鍵從主鍵索引中查到具體行的數(shù)據(jù),后面的通過(guò)得到的主鍵從主鍵索引中獲取數(shù)據(jù)的過(guò)程被稱(chēng)為回表。

回表的過(guò)程使得通過(guò)普通索引查詢(xún)較主鍵索引查詢(xún)多了一步,在很多情況下效率相對(duì)較低。所以在我們的查詢(xún)過(guò)程中如果能夠僅通過(guò)主鍵確定數(shù)據(jù)那最好就是直接使用主鍵進(jìn)行查詢(xún)。

覆蓋索引

上面介紹了通過(guò)非主鍵查詢(xún)會(huì)有一個(gè)回表的過(guò)程,但是需要注意的是并不是每一個(gè)查詢(xún)都存在回表這一步,對(duì)于一個(gè)普通索引來(lái)說(shuō)其葉節(jié)點(diǎn)存儲(chǔ)的是主鍵的值,那么假設(shè)我現(xiàn)在需要的數(shù)據(jù)也僅僅就是主鍵的值呢?通過(guò)普通索引取到主鍵的值后就并不需要再到主鍵索引中查,那么也就不存在回表這一過(guò)程了。

上面例子中該非主鍵索引已經(jīng)存在了我們所需要的值,所以該索引也被稱(chēng)為覆蓋索引。覆蓋索引并不是一個(gè)固定的結(jié)構(gòu),可以使單索引(一個(gè)字段的索引),也可以使復(fù)合索引,凡是能夠直接提供查詢(xún)結(jié)果而不需要進(jìn)行回表過(guò)程的都可以被稱(chēng)為覆蓋索引。

很多時(shí)候我們不可能僅僅通過(guò)主鍵來(lái)確定數(shù)據(jù),使用普通索引可能會(huì)導(dǎo)致低效,所以覆蓋索引在日常開(kāi)發(fā)過(guò)程中也是一個(gè)很常用的性能優(yōu)化的手段。

當(dāng)然覆蓋索引頁(yè)并不都是好的,比如我現(xiàn)在建立了一個(gè)索引index(a,b)。由a,b兩個(gè)字段來(lái)建立索引,好處已經(jīng)說(shuō)過(guò)了就是查詢(xún)ab字段時(shí)不會(huì)回表,但是如果僅僅通過(guò)b字段來(lái)查詢(xún)就無(wú)法走這個(gè)索引了。建立的索引的索引項(xiàng)是按照索引定義里面出現(xiàn)的字段順序排序的。

最左前綴原則

假設(shè)現(xiàn)在存在索引index(a,b),那么如果通過(guò)a和b來(lái)查詢(xún)能夠應(yīng)用該索引,單獨(dú)使用a來(lái)查詢(xún)也能應(yīng)用到該索引,但是如果單獨(dú)使用b來(lái)查詢(xún)則無(wú)法應(yīng)用到該索引。這就是最左前綴原則,在匹配索引時(shí)回匹配索引最左邊的n個(gè)字段,能匹配上就可以應(yīng)用該索引。

由于最左前綴原則的存在也就要求我們?cè)诮⑺饕龝r(shí)可能需要考慮更多的事情。

首先需要清楚的事索引是一種數(shù)據(jù)結(jié)構(gòu),建立索引時(shí)需要消耗存儲(chǔ)空間的,所以索引并不是建立的越多越好,而是應(yīng)該根據(jù)需求盡可能的減少索引的數(shù)量。

而最左前綴原則的存在就使得一個(gè)聯(lián)合索引可以被當(dāng)成多個(gè)索引來(lái)使用,當(dāng)然前提是設(shè)計(jì)好索引中字段的順序(實(shí)際上最左前綴原則也并不是僅僅適用于聯(lián)合索引,對(duì)于字符串索引也使用,字符串索引中最左n個(gè)字符相當(dāng)于聯(lián)合索引中的最左n個(gè)字段)。

比如index(a,b),有了這個(gè)索引后我們就不需要單獨(dú)為a建立索引,所以在設(shè)計(jì)聯(lián)合索引時(shí)一般將使用頻率較高的字段放在前面。

然后是將區(qū)分度較高的字段靠前,區(qū)分度就是字段中值的重復(fù)率,重復(fù)率越低區(qū)分度越高。比如性別就不適合作為索引,區(qū)分度越高的字段經(jīng)過(guò)一次篩選能過(guò)濾掉更多的行。

然后還需要考慮的是字段的大小,由于索引也需要占據(jù)空間所以一般選用較小的字段。

MySQL中的索引有哪些類(lèi)型或者種類(lèi)就先給大家講到這里,對(duì)于其它相關(guān)問(wèn)題大家想要了解的可以持續(xù)關(guān)注我們的行業(yè)資訊。我們的板塊內(nèi)容每天都會(huì)捕捉一些行業(yè)新聞及專(zhuān)業(yè)知識(shí)分享給大家的。


本文名稱(chēng):MySQL中的索引有哪些類(lèi)型或者種類(lèi)
網(wǎng)頁(yè)鏈接:http://weahome.cn/article/gggedh.html

其他資訊

在線(xiàn)咨詢(xún)

微信咨詢(xún)

電話(huà)咨詢(xún)

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部