面試不要再問(wèn)“索引基礎(chǔ)知識(shí)”了

1 什么是索引

索引可加快檢索的速度囚聚,提升查詢(xún)性能跨晴,當(dāng)前關(guān)系型數(shù)據(jù)庫(kù)普遍采用的B+樹(shù)索引,此索引是一種按字段排序的樹(shù)形目錄結(jié)構(gòu)根吁,主要用于提升查詢(xún)性能和唯一約束支持员淫。它的內(nèi)容包括根節(jié)點(diǎn)、分支節(jié)點(diǎn)和葉子節(jié)點(diǎn)击敌。根節(jié)點(diǎn)和分支節(jié)點(diǎn)主要保存了索引樹(shù)的順序以及各層級(jí)間引用關(guān)系介返;葉子節(jié)點(diǎn)保存索引字段內(nèi)容(針對(duì)聚集索引存儲(chǔ)的是實(shí)際數(shù)據(jù),針對(duì)非聚集索引沃斤,存儲(chǔ)的是聚集索引葉子節(jié)點(diǎn)的地址)圣蝎。

索引的創(chuàng)建就是為了提升查詢(xún)性能,索引就是把查詢(xún)語(yǔ)句所需要的少量數(shù)據(jù)記錄到索引分頁(yè)中衡瓶,這樣訪問(wèn)數(shù)據(jù)時(shí)徘公,只要訪問(wèn)少量數(shù)據(jù)的索引分頁(yè)就可以了。

  • 并不是索引越多越好哮针,建少了关面,用where子句找數(shù)據(jù)效率比較低坦袍,建多了,執(zhí)行增等太、刪捂齐、改操作時(shí),會(huì)額外的更新索引缩抡,導(dǎo)致性能較慢奠宜,同時(shí),索引占用了磁盤(pán)空間缝其,過(guò)多的索引也會(huì)導(dǎo)致空間浪費(fèi)挎塌。
  • 并不是有索引一定比沒(méi)有索引要好。對(duì)于數(shù)據(jù)量較少的表内边,不需要?jiǎng)?chuàng)建索引榴都,因?yàn)橛兴饕龝r(shí),系統(tǒng)首先會(huì)去尋找索引頁(yè)漠其,然后再去找實(shí)際的數(shù)據(jù)項(xiàng)嘴高。

2 索引分類(lèi)

索引分為兩大類(lèi):聚集索引和非聚集索引,其中和屎,非聚集索引又可細(xì)分為普通索引拴驮、唯一索引、組合索引柴信。

2.1 聚集索引

聚集索引規(guī)定了表中數(shù)據(jù)的物理存放順序套啤,數(shù)據(jù)行的物理順序與列值(一般是主鍵的那一列)的邏輯順序相同,一個(gè)表中只能擁有一個(gè)聚集索引随常,可以類(lèi)比于字典中的按拼音目錄潜沦。它的優(yōu)勢(shì)在于:查詢(xún)小數(shù)據(jù)量的表;查詢(xún)指定范圍內(nèi)的數(shù)據(jù)绪氛。

在MySQL數(shù)據(jù)庫(kù)的InnoDB存儲(chǔ)引擎中唆鸡,主鍵索引就是聚集索引,所有數(shù)據(jù)都會(huì)按照主鍵索引進(jìn)行組織枣察;而在MyISAM存儲(chǔ)引擎中争占,就沒(méi)有聚集索引了,因?yàn)镸yISAM存儲(chǔ)引擎中的數(shù)據(jù)不是按索引順序進(jìn)行存儲(chǔ)的序目。

(1)聚集索引特點(diǎn):

  • 聚集索引的葉節(jié)點(diǎn)就是實(shí)際數(shù)據(jù)頁(yè)臂痕;
  • 在數(shù)據(jù)頁(yè)中數(shù)據(jù)按照索引順序存放;
  • 行的物理位置和其在索引中的位置是相同的宛琅;
  • 每個(gè)表只能有一個(gè)聚集索引刻蟹。

(2)聚集索引不適用的場(chǎng)景

  • 數(shù)據(jù)列頻繁更改,這將導(dǎo)致整行移動(dòng)嘿辟。

2.2 非聚集索引

(1)非聚集索引是獨(dú)立于數(shù)據(jù)表之外的結(jié)構(gòu)舆瘪,即數(shù)據(jù)存放在一個(gè)地方片效,索引存放在另一個(gè)地方,索引葉子節(jié)點(diǎn)通過(guò)其自帶的指針指向數(shù)據(jù)的存儲(chǔ)位置(聚集索引葉子節(jié)點(diǎn))英古。
(2)表中的非聚集索引可以創(chuàng)建多個(gè)淀衣,可以為表常用的每個(gè)列都創(chuàng)建一個(gè)非聚集索引(索引個(gè)數(shù)適當(dāng)就好,不要貪多)召调。
(3)形象的描述非聚集索引膨桥,可以用這個(gè)例子:一本介紹園藝的書(shū)可能包含一個(gè)植物通俗名稱(chēng)索引和一個(gè)植物學(xué)名索引,這兩個(gè)索引就是非聚集索引唠叛。每當(dāng)我們想看一個(gè)植物的詳細(xì)信息時(shí)只嚣,先通過(guò)名稱(chēng)定為到頁(yè)數(shù),然后查看具體詳情艺沼。

2.3 聚集索引和非聚集索引比較

(1)概念層次

  • 聚集索引:物理存儲(chǔ)按照索引排序册舞,就像字典正文,我們按照正文的字母順序就能找到我們的記錄障般。
  • 非聚集索引:物理存儲(chǔ)不按照索引排序调鲸,就像偏旁查字法目錄,每個(gè)偏旁目錄下的字的頁(yè)碼不是順序的挽荡。

(2)速度方面

  • 聚集索引:插入數(shù)據(jù)時(shí)藐石,速度較慢(時(shí)間主要花費(fèi)在“物理存儲(chǔ)的排序”上,也就是首先要找到位置然后再插入數(shù)據(jù))定拟。但查詢(xún)數(shù)據(jù)的速度比非聚集索引要快于微。

(3)個(gè)數(shù)方面

  • 聚集索引:每個(gè)表只能有一個(gè)聚集索引,默認(rèn)主鍵是聚集索引青自,但經(jīng)常業(yè)務(wù)上是不合適的角雷,一定要將聚集索引建立在下面兩種場(chǎng)景:第一,最頻繁使用的性穿、用以縮小查詢(xún)范圍的字段上;第二雷滚,最頻繁使用的需曾、需要排序的字段上。
  • 非聚集索引:每個(gè)表可以創(chuàng)建多個(gè)祈远。

(4)實(shí)際舉例說(shuō)明
我們的漢語(yǔ)字典的正文本身就是一個(gè)聚集索引呆万。比如,我們要查“安”字车份,就會(huì)很自然地翻開(kāi)字典的前幾頁(yè)谋减,因?yàn)椤鞍病钡钠匆羰恰癮n”,而按照拼音排序漢字的字典是以英文字母“a”開(kāi)頭并以“z”結(jié)尾的扫沼,那么“安”字就自然地排在字典的前部出爹。如果您翻完了所有以“a”開(kāi)頭的部分仍然找不到這個(gè)字庄吼,那么就說(shuō)明您的字典中沒(méi)有這個(gè)字;同樣的严就,如果查“張”字总寻,那您也會(huì)將您的字典翻到最后部分,因?yàn)椤皬垺钡钠匆羰恰皕hang”梢为。也就是說(shuō)渐行,字典的正文部分本身就是一個(gè)目錄,您不需要再去查其他目錄來(lái)找到您需要找的內(nèi)容铸董。我們把這種正文內(nèi)容本身就是一種按照一定規(guī)則排列的目錄稱(chēng)為“聚集索引”祟印。

如果您認(rèn)識(shí)某個(gè)字,您可以快速地從拼音表中查到這個(gè)字粟害。但您也可能會(huì)遇到您不認(rèn)識(shí)的字蕴忆,不知道它的發(fā)音,這時(shí)候我磁,您就不能按照剛才的方法找到您要查的字孽文,而需要去根據(jù)“偏旁部首”查到您要找的字,然后根據(jù)這個(gè)字后的頁(yè)碼直接翻到某頁(yè)來(lái)找到您要找的字夺艰。但您結(jié)合“部首目錄”和“檢字表”而查到的字的排序并不是真正的正文的排序方法芋哭,比如您查“張”字,我們可以看到在查部首之后的檢字表中“張”的頁(yè)碼是672頁(yè)郁副,檢字表中“張”的上面是“馳”字减牺,但頁(yè)碼卻是63頁(yè),“張”的下面是“弩”字存谎,頁(yè)面是390頁(yè)拔疚。很顯然,這些字并不是真正的分別位于“張”字的上下方既荚,現(xiàn)在您看到的連續(xù)的“馳稚失、張、弩”三字實(shí)際上就是他們?cè)诜蔷奂饕械呐判蚯∑福亲值湔闹械淖衷诜蔷奂饕械挠成渚涓鳌N覀兛梢酝ㄟ^(guò)這種方式來(lái)找到您所需要的字,但它需要兩個(gè)過(guò)程晴叨,先找到目錄中的結(jié)果凿宾,然后再翻到您所需要的頁(yè)碼。我們把這種目錄純粹是目錄兼蕊,正文純粹是正文的排序方式稱(chēng)為“非聚集索引”初厚。

(5)使用場(chǎng)景對(duì)比

動(dòng)作描述 使用聚集索引 使用非聚集索引
列經(jīng)常被分組排序
返回某范圍內(nèi)的數(shù)據(jù)
一個(gè)或極少不同值
小數(shù)目的不同值
大數(shù)目的不同值
頻繁更新的列
外鍵列
主鍵列
頻繁修改索引列

2.4 聚集索引和非聚集索引常見(jiàn)問(wèn)題

(1)聚集索引的約束是唯一性,是否要求字段也是唯一的呢
分析:如果認(rèn)為是的朋友孙技,可能是受系統(tǒng)默認(rèn)設(shè)置的影響产禾,一般我們指定一個(gè)表的主鍵排作,如果這個(gè)表之前沒(méi)有聚集索引,同時(shí)建立主鍵時(shí)候沒(méi)有強(qiáng)制指定使用非聚集索引下愈,SQL會(huì)默認(rèn)在此字段上創(chuàng)建一個(gè)聚集索引纽绍,而主鍵都是唯一的,所以理所當(dāng)然的認(rèn)為創(chuàng)建聚集索引的字段也需要唯一势似。
結(jié)論:聚集索引可以創(chuàng)建在任何一列你想創(chuàng)建的字段上拌夏,這是從理論上講,實(shí)際情況并不能隨便指定履因,否則在性能上會(huì)是惡夢(mèng)障簿。

(2)在數(shù)據(jù)庫(kù)中通過(guò)什么描述聚集索引與非聚集索引的?
可以這樣區(qū)分兩者的區(qū)別:聚集索引的葉節(jié)點(diǎn)就是最終的數(shù)據(jù)節(jié)點(diǎn)栅迄,而非聚集索引的葉節(jié)仍然是索引節(jié)點(diǎn)站故,但它有一個(gè)指向最終數(shù)據(jù)的指針。

4 索引使用注意事項(xiàng)

4.1 索引不會(huì)包含有NULL值的列

只要列中包含有NULL值都將不會(huì)被包含在索引中毅舆,組合索引中只要有一列含有NULL值西篓,那么這一列對(duì)于此組合索引就是無(wú)效的。所以我們?cè)跀?shù)據(jù)庫(kù)設(shè)計(jì)時(shí)不要讓字段的默認(rèn)值為NULL憋活。

4.2 使用短索引

對(duì)串列進(jìn)行索引岂津,如果可能的話,應(yīng)該指定一個(gè)前綴長(zhǎng)度悦即。例如吮成,有一個(gè)CHAR(255)的列,如果在前10個(gè)或20個(gè)字符內(nèi)辜梳,多數(shù)值是惟一的粱甫,那么就不要對(duì)整個(gè)列進(jìn)行索引。短索引不僅可以提高查詢(xún)速度而且可以節(jié)省磁盤(pán)空間和I/O操作作瞄。

4.3 索引列排序

MySQL查詢(xún)只使用一個(gè)索引茶宵,因此如果where子句中已經(jīng)使用了索引的話,那么order by中的列是不會(huì)使用索引的宗挥。因此节预,數(shù)據(jù)庫(kù)默認(rèn)排序可以符合要求的情況下不要使用排序操作;盡量不要包含多個(gè)列的排序属韧,如果需要最好給這些列創(chuàng)建組合索引。

4.4 like語(yǔ)句操作

一般情況下不鼓勵(lì)使用like操作蛤吓,如果非使用不可宵喂,不要將匹配符放于匹配字符串最前面,比如:like “%aaa%” 不會(huì)使用索引会傲,而like “aaa%”可以使用索引锅棕。

4.5 不要在列上進(jìn)行運(yùn)算

例如:select * from users where YEAR(adddate)<2007拙泽,將在每個(gè)行上進(jìn)行運(yùn)算,這將導(dǎo)致索引失效而進(jìn)行全表掃描裸燎,因此我們可以改成:

select * from users where adddate<’2007-01-01′

關(guān)于這一點(diǎn)可以圍觀:一個(gè)單引號(hào)引發(fā)的MYSQL性能損失顾瞻。

5 哪些場(chǎng)景會(huì)使索引失效

(1)以“%”開(kāi)頭的LIKE語(yǔ)句,模糊匹配
(2)OR語(yǔ)句前后沒(méi)有同時(shí)使用索引
(3)數(shù)據(jù)類(lèi)型出現(xiàn)隱式轉(zhuǎn)化(如varchar不加單引號(hào)的話可能會(huì)自動(dòng)轉(zhuǎn)換為int型)
(4)帶非操作符德绿,如<>/!=/not in/not exist
(5)列上作運(yùn)算
最后總結(jié)一下荷荤,MySQL只對(duì)以下操作符才使用索引:<,<=,=,>,>=,between,in,以及某些時(shí)候的like(不以通配符%或_開(kāi)頭的情形),而對(duì)于<>移稳,not in是不會(huì)使用索引的蕴纳。而理論上每張表里面最多可創(chuàng)建16個(gè)索引,不過(guò)除非是數(shù)據(jù)量真的很多个粱,否則過(guò)多的使用索引也不是那么好玩的古毛。

6 哪些場(chǎng)景需要?jiǎng)?chuàng)建索引

(1)不一定要?jiǎng)?chuàng)建索引,可通過(guò)優(yōu)化sql實(shí)現(xiàn)都许。
(2)避免對(duì)經(jīng)常更新的表進(jìn)行過(guò)多的索引稻薇,并且索引中的列盡可能少。而對(duì)經(jīng)常用于查詢(xún)的字段(外鍵)應(yīng)該創(chuàng)建索引胶征,但要避免添加不必要的字段
(3)數(shù)據(jù)量小的表最好不要使用索引塞椎,由于數(shù)據(jù)較少,查詢(xún)花費(fèi)的時(shí)間可能比遍歷索引的時(shí)間還要短弧烤,索引可能不會(huì)產(chǎn)生優(yōu)化效果忱屑。
(4)在條件表達(dá)式中經(jīng)常用到的、不同值較多(主鍵的列)的列上建立索引暇昂,在不同值少的列上不要建立索引莺戒。比如在學(xué)生表的“性別”字段上只有“男”與“女”兩個(gè)不同值,因此就無(wú)須建立索引急波。如果建立索引从铲,不但不會(huì)提高查詢(xún)效率,反而會(huì)嚴(yán)重降低更新速度澄暮。
(5)在頻繁進(jìn)行排序或分組(即進(jìn)行GROUPBY或ORDERBY操作)的列上建立索引名段,如果待排序的列有多個(gè),可以在這些列上建立組合索引泣懊。在經(jīng)常使用WHERE子句中的列上面創(chuàng)建索引伸辟,加快條件的判斷速度。對(duì)于那些定義為text, image和bit數(shù)據(jù)類(lèi)型的列不應(yīng)該增加索引馍刮。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末信夫,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌静稻,老刑警劉巖警没,帶你破解...
    沈念sama閱讀 219,188評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異振湾,居然都是意外死亡杀迹,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)押搪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)树酪,“玉大人,你說(shuō)我怎么就攤上這事嵌言⌒峄兀” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,562評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵摧茴,是天一觀的道長(zhǎng)绵载。 經(jīng)常有香客問(wèn)我,道長(zhǎng)苛白,這世上最難降的妖魔是什么娃豹? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,893評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮购裙,結(jié)果婚禮上懂版,老公的妹妹穿的比我還像新娘。我一直安慰自己躏率,他們只是感情好躯畴,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,917評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著薇芝,像睡著了一般蓬抄。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上夯到,一...
    開(kāi)封第一講書(shū)人閱讀 51,708評(píng)論 1 305
  • 那天嚷缭,我揣著相機(jī)與錄音,去河邊找鬼耍贾。 笑死阅爽,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的荐开。 我是一名探鬼主播付翁,決...
    沈念sama閱讀 40,430評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼晃听!你這毒婦竟也來(lái)了胆敞?” 一聲冷哼從身側(cè)響起着帽,我...
    開(kāi)封第一講書(shū)人閱讀 39,342評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎移层,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體赫粥,經(jīng)...
    沈念sama閱讀 45,801評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡观话,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,976評(píng)論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了越平。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片频蛔。...
    茶點(diǎn)故事閱讀 40,115評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖秦叛,靈堂內(nèi)的尸體忽然破棺而出晦溪,到底是詐尸還是另有隱情,我是刑警寧澤挣跋,帶...
    沈念sama閱讀 35,804評(píng)論 5 346
  • 正文 年R本政府宣布三圆,位于F島的核電站,受9級(jí)特大地震影響避咆,放射性物質(zhì)發(fā)生泄漏舟肉。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,458評(píng)論 3 331
  • 文/蒙蒙 一查库、第九天 我趴在偏房一處隱蔽的房頂上張望路媚。 院中可真熱鬧,春花似錦樊销、人聲如沸整慎。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,008評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)裤园。三九已至,卻和暖如春够吩,著一層夾襖步出監(jiān)牢的瞬間比然,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,135評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工周循, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留强法,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,365評(píng)論 3 373
  • 正文 我出身青樓湾笛,卻偏偏與公主長(zhǎng)得像饮怯,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子嚎研,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,055評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • SQL SERVER提供了多種索引蓖墅。如果以存儲(chǔ)結(jié)構(gòu)結(jié)構(gòu)來(lái)區(qū)分库倘,有聚集索引和非聚集索引;如果以數(shù)據(jù)的唯一性來(lái)區(qū)分论矾,則...
    不知名的蛋撻閱讀 6,034評(píng)論 0 5
  • 之前的文章一直在規(guī)避索引的建立去優(yōu)化數(shù)據(jù)庫(kù)贪壳,不是不想講饱亿,而是這個(gè)太重要,必須抽出來(lái)講闰靴。今天我們就來(lái)研究下數(shù)據(jù)庫(kù)索引...
    JackFrost_fuzhu閱讀 4,741評(píng)論 0 70
  • 索引的基本原理彪笼,以及數(shù)據(jù)是如何被訪問(wèn)的 (一)SQLS如何訪問(wèn)沒(méi)有建立索引的數(shù)據(jù)表 Heap譯成漢語(yǔ)叫做“堆”,其...
    安易學(xué)車(chē)閱讀 3,451評(píng)論 0 8
  • ORA-00001: 違反唯一約束條件 (.) 錯(cuò)誤說(shuō)明:當(dāng)在唯一索引所對(duì)應(yīng)的列上鍵入重復(fù)值時(shí)蚂且,會(huì)觸發(fā)此異常配猫。 O...
    我想起個(gè)好名字閱讀 5,320評(píng)論 0 9
  • 索引 數(shù)據(jù)庫(kù)中的查詢(xún)操作非常普遍泵肄,索引就是提升查找速度的一種手段 索引的類(lèi)型 從數(shù)據(jù)結(jié)構(gòu)角度分 1.B+索引:傳統(tǒng)...
    一凡呀閱讀 2,920評(píng)論 0 8