您好,登錄后才能下訂單哦!
這篇文章給大家介紹該如何進(jìn)行MySQL的索引分類,內(nèi)容非常詳細(xì),感興趣的小伙伴們可以參考借鑒,希望對(duì)大家能有所幫助。
MySQL的索引分類問題一直讓人頭疼,幾乎所有的資料都會(huì)給你列一個(gè)長(zhǎng)長(zhǎng)的清單,給你介紹什么主鍵索引、單值索引,覆蓋索引,自適應(yīng)哈希索引,全文索引,聚簇索引,非聚簇索引等……給人的感覺就是云里霧里,好像MySQL索引的實(shí)現(xiàn)方式有很多種,但是都沒有一個(gè)清晰的分類。所以本人嘗試總結(jié)了一下如何給MySQL的索引類型分類,便于大家記憶,由于MySQL中支持多種存儲(chǔ)引擎,在不同的存儲(chǔ)引擎中實(shí)現(xiàn)略微有所差距,下文中如果沒有特殊聲明,默認(rèn)指的都是InnoDB存儲(chǔ)引擎。
索引從不同維度劃分可以有很多種名稱,但是需要明確一個(gè)問題——索引的本質(zhì)是一種數(shù)據(jù)結(jié)構(gòu),其他索引的劃分則是針對(duì)實(shí)際應(yīng)用而言。
索引是提高查詢效率的數(shù)據(jù)結(jié)構(gòu),而能夠提高查詢效率的數(shù)據(jù)結(jié)構(gòu)有很多,如二叉搜索樹,紅黑樹,跳表,哈希表(散列表)等,而MySQL中用到了B+Tree和散列表(Hash表)作為索引的底層數(shù)據(jù)結(jié)構(gòu)(其實(shí)也用到了跳表實(shí)現(xiàn)全文索引,但這不是重要考點(diǎn),所以可以忽略)。
MySQL并沒有顯式支持Hash索引,而是作為內(nèi)部的一種優(yōu)化。具體在Innodb存儲(chǔ)引擎里,會(huì)監(jiān)控對(duì)表上二級(jí)索引的查找,如果發(fā)現(xiàn)某二級(jí)索引被頻繁訪問,二級(jí)索引成為熱數(shù)據(jù),就為之建立hash索引。因此,在MySQL的Innodb里,對(duì)于熱點(diǎn)的數(shù)據(jù)會(huì)自動(dòng)生成Hash索引。這種hash索引,根據(jù)其使用的場(chǎng)景特點(diǎn),也叫自適應(yīng)Hash索引。
這個(gè)是MySQL索引的基本實(shí)現(xiàn)方式。除了全文索引、hash索引,Innodb、MyISAM的索引都是通過B+樹實(shí)現(xiàn)的。
為了能應(yīng)對(duì)不同的數(shù)據(jù)檢索需求,索引既可以僅包含一個(gè)字段,也可以同時(shí)包含多個(gè)字段。單個(gè)字段組成的索引可以稱為單值索引,否則稱之為復(fù)合索引,也稱為組合索引或多值索引。
這個(gè)很好理解,假如我們有一張表,有三個(gè)屬性,分別是 id,age 和 name 。假如在id上建立索引,那這就是單值索引;如果在 name 和 age 上建立索引,那這就是復(fù)合索引。
復(fù)合索引的索引的數(shù)據(jù)順序跟字段的順序相關(guān),包含多個(gè)值的索引中,如果當(dāng)前面字段的值重復(fù)時(shí),將會(huì)按照其后面的值進(jìn)行排序。
使用覆蓋索引的前提是字段長(zhǎng)度比較短,對(duì)于值長(zhǎng)度較長(zhǎng)的字段則不適合使用覆蓋索引,原因有很多,比如索引一般存儲(chǔ)在內(nèi)存中,如果占用空間較大,則可能會(huì)從磁盤中加載,影響性能。
MySQL中是根據(jù)主鍵來組織數(shù)據(jù)的,所以每張表都必須有主鍵索引,主鍵索引只能有一個(gè),不能為null同時(shí)必須保證唯一性。建表時(shí)如果沒有指定主鍵索引,則會(huì)自動(dòng)生成一個(gè)隱藏的字段作為主鍵索引。
如果不是主鍵索引,則就可以稱之為非主鍵索引,又可以稱之為輔助索引或者二級(jí)索引。主鍵索引的葉子節(jié)點(diǎn)存儲(chǔ)了完整的數(shù)據(jù)行,而非主鍵索引的葉子節(jié)點(diǎn)存儲(chǔ)的則是主鍵索引值,通過非主鍵索引查詢數(shù)據(jù)時(shí),會(huì)先查找到主鍵索引,然后再到主鍵索引上去查找對(duì)應(yīng)的數(shù)據(jù)。
在這里假設(shè)我們有張表user,具有三列:ID,age,name,create_time,id是主鍵,(age,create_time,,name)建立輔助索引。執(zhí)行如下sql語句:
select name from user where age>2 order by create_time desc。
正常的話,查詢分兩步:
1.按照輔助索引,查找到記錄的主鍵,
2.按照主鍵主鍵索引里查找記錄,返回name。
但實(shí)際上,我們可以看到,輔助索引節(jié)點(diǎn)是按照age,create_time,name建立的,索引信息里完全包含我們所要的信息,如果能從輔助索引里返回name信息,則第二步是完全沒有必要的,可以極大提升查詢速度。
按照這種思想Innodb里針對(duì)使用輔助索引的查詢場(chǎng)景做了優(yōu)化,叫覆蓋索引(在這里小聲吐槽一下,不知道業(yè)界起這種名詞干嘛,太容易引起歧義了,叫個(gè)索引覆蓋查詢不是更好嗎)。
根據(jù)數(shù)據(jù)與索引的存儲(chǔ)關(guān)聯(lián)性,可以分為聚簇索引和非聚簇索引(也叫聚集索引和非聚集索引)。聚簇索引也叫簇類索引,是一種對(duì)磁盤上實(shí)際數(shù)據(jù)重新組織以按指定的一個(gè)或多個(gè)列的值排序。整個(gè)簡(jiǎn)潔的說法,這倆的區(qū)別就是索引的存儲(chǔ)順序和數(shù)據(jù)的存儲(chǔ)順序是否是關(guān)系的,有關(guān)就是聚簇索引,無關(guān)就是非聚簇索引。具體實(shí)現(xiàn)方式根據(jù)索引的數(shù)據(jù)結(jié)構(gòu)不同會(huì)有所不同。下面以B+樹實(shí)現(xiàn)的索引為例,舉例來說明聚簇索引和非聚簇索引。
Innodb的主鍵索引,非葉子節(jié)點(diǎn)存儲(chǔ)的是索引指針,葉子節(jié)點(diǎn)存儲(chǔ)的是既有索引也有數(shù)據(jù),是典型的聚簇索引(這里可以發(fā)現(xiàn),索引和數(shù)據(jù)的存儲(chǔ)順序是強(qiáng)相關(guān)的。因此是典型的聚簇索引),如圖:
MyISAM中索引和數(shù)據(jù)文件分開存儲(chǔ),B+Tree的葉子節(jié)點(diǎn)存儲(chǔ)的是數(shù)據(jù)存放的地址,而不是具體的數(shù)據(jù),是典型的非聚簇索引;換言之,數(shù)據(jù)可以在磁盤上隨便找地方存,索引也可以在磁盤上隨便找地方存,只要葉子節(jié)點(diǎn)記錄對(duì)了數(shù)據(jù)存放地址就行。因此,索引存儲(chǔ)順序和數(shù)據(jù)存儲(chǔ)關(guān)系毫無關(guān)聯(lián),是典型的非聚簇索引,另外Inndob里的輔助索引也是非聚簇索引。
顧名思義,不允許具有索引值相同的行,從而禁止重復(fù)的索引或鍵值。系統(tǒng)在創(chuàng)建該索引時(shí)檢查是否有重復(fù)的鍵值,并在每次使用 INSERT 或 UPDATE 語句添加數(shù)據(jù)時(shí)進(jìn)行檢查, 如果有重復(fù)的值,則會(huì)操作失敗,拋出異常。
需要注意的是,主鍵索引一定是唯一索引,而唯一索引不一定是主鍵索引。唯一索引可以理解為僅僅是將索引設(shè)置一個(gè)唯一性的屬性。
在MySQL 5.6版本以前,只有MyISAM存儲(chǔ)引擎支持全文引擎。在5.6版本中,InnoDB加入了對(duì)全文索引的支持,但是不支持中文全文索引.在5.7.6版本,MySQL內(nèi)置了ngram全文解析器,用來支持亞洲語種的分詞。主要用來利用關(guān)鍵詞查詢文本,不是MySQL的主要面向場(chǎng)景,使用較少,這里就不展開討論了。
最后總結(jié)一張腦圖方便記憶:
關(guān)于該如何進(jìn)行MySQL的索引分類就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。