1. where右邊使用獨立的列
2. 前綴索引和索引選擇性
前綴索引:索引最開始的部分字符,可以大大節(jié)約索引空間如暖,從而提供索引效率;
索引選擇性:不重復(fù)的索引值和數(shù)據(jù)表記錄的總數(shù)的比值已卷,范圍在0-1之間朵逝,比值越大,表示索引的選擇性越高坷襟,則查詢效率越高奸柬。
3 對于blob,text或很長的varchar類型的列婴程,必須使用前綴索引廓奕,因為MySQL不允許索引這些列的完整長度。
demo分析如下:
于是档叔,我們此時可以確定合適的前綴索引:
ALTER TABLE sakila.city_demo ADD KEY (city(7));
4.多列索引
在多個列上建立獨立的單列索引大部分情況下并不能提高MySQL的查詢性能桌粉。
- 當(dāng)服務(wù)器對多個索引做相交操作時(通常是多個AND條件),通常意味著需要一個包含所有相關(guān)列的多列索引蹲蒲,而不是多個獨立的單列索引番甩;
- 當(dāng)服務(wù)器對多個索引做聯(lián)合操作時(通常有多個OR條件)侵贵,通常需要耗費大量CPU和內(nèi)存資源在算法的緩存届搁、排序和合并操作上,特別是其中有些索引的選擇性不高窍育,需要合并掃描返回的大量數(shù)據(jù)的時候卡睦;
- 更重要的是,優(yōu)化器不會把這些計算到“查詢成本”中漱抓,優(yōu)化器只關(guān)心隨機頁面讀取表锻。這會使得查詢的成本被低估,導(dǎo)致執(zhí)行計劃還不如直接走全表掃描乞娄。這樣做不但會消耗更多的CPU和內(nèi)存資源瞬逊,還可能影響查詢的并發(fā)性,還不如在MySQL更早的版本一樣仪或,將查詢改寫成union的方式往往更好确镊。、
5 選擇合適的索引列順序
索引的順序依賴于使用該索引的查詢范删,并且同時需要考慮如何更好地滿足排序和分組的需要(下面內(nèi)容適用B-tree索引)蕾域。
在一個多列的B-tree索引中,索引列的順序意味著索引首先按照最左列進行排序,其次是第二列旨巷,所以巨缘,索引可以按照升序或者降序進行掃描,以滿足精確符號列順序的ORDER BY采呐、GROUP BY和DISTINCT等子句的查詢需求若锁。
如何選擇列順序有一個經(jīng)驗法則:將選擇性最高的列放到索引的最前列。然而這通常不如避免隨機IO和排序那么重要懈万,考慮這個問題需要更全面拴清。
當(dāng)不需要考慮排序和分組時,將選擇性最高的列放在前面通常是最好的会通。這時候索引的作用只是用于優(yōu)化Where條件的查找口予。然而,性能不只是依賴所有索引列的選擇性(整體基數(shù))涕侈,也和查詢條件的具體值有關(guān)沪停,也就是和值的分布有關(guān)。這和前面說的選擇前綴的長度需要考慮的地方一樣裳涛,可能需要根據(jù)哪些運行頻率最高的查詢來調(diào)整索引列的順序木张,讓這種情況下索引的選擇性最高。
demo如下:
6 聚簇索引
聚簇索引不是一種單獨的索引類型端三,而是一種數(shù)據(jù)存儲方式舷礼。InnoDB聚簇索引實際上在同一個結(jié)構(gòu)中保存了B-tree索引和數(shù)據(jù)行。當(dāng)表有聚簇索引時郊闯,它的索引行實際上存放在索引的葉子頁中妻献。術(shù)語“聚簇”表示數(shù)據(jù)行和相鄰的鍵值緊湊地存儲在一起。因為無法同時把數(shù)據(jù)行存放在兩個不同的地方团赁,所以一個表只能有一個聚簇索引育拨。
7 覆蓋索引
通常大家都會根據(jù)查詢的where條件來創(chuàng)建合適的索引,不過這只是索引優(yōu)化的一個方面欢摄。設(shè)計優(yōu)秀的索引應(yīng)該考慮到整個查詢熬丧,而不單單是where條件部分。索引確實是一種查找數(shù)據(jù)的高效方式怀挠,但是MySQL也可以使用索引來直接獲取列的數(shù)據(jù)析蝴,這樣就不需要讀取數(shù)據(jù)行。如果索引的葉子節(jié)點中已經(jīng)包含要查詢的數(shù)據(jù)绿淋,那么還有什么必要回表查詢呢闷畸?如果一個索引包含(或者說覆蓋)所有需要查詢的字段的值,我們就稱之為“覆蓋索引”躬它。
不是所有的類型的索引都可以成為覆蓋索引腾啥。覆蓋索引必須要存儲索引列的值,而哈希索引、空間索引和全文索引等都不存儲索引列的值倘待。所以MySQL只能使用Be-tree所以做覆蓋索引疮跑。
demo1:
demo2:
有辦法解決以上的兩個問題,需要重寫查詢并巧妙地設(shè)計索引凸舵。先將索引擴展至覆蓋三個數(shù)據(jù)列(artist祖娘,title,prod_id)啊奄,然后按如下方式重寫查詢:
8 使用索引掃描來做排序
MySQL有兩種方式可以生成有序的結(jié)果:1.排序操作渐苏;2.按索引順序掃描。
如果Explain出來的type列的值是“index”,則說明使用了索引掃描來做排序菇夸。
掃描索引本身是很快的琼富,因為只需要從一條索引記錄移動到緊接著的下一條記錄。但如果索引不能覆蓋查詢所需的全部列庄新,那就不得不掃描每一條索引記錄就都回表查詢一次對應(yīng)的行鞠眉。這基本上都是隨機I/O,因此按索引順序讀取數(shù)據(jù)的速度通常要比順序地全表掃描慢择诈,尤其是在I/O密集型的工作負載時械蹋。
MySQL可以使用同一個所以既滿足排序,又用于查找行羞芍,因此哗戈,如果可能,設(shè)計索引應(yīng)該盡可能同時滿足這兩種任務(wù)荷科,這樣是最好的唯咬。
只有當(dāng)索引的列順序和ORDER BY子句的順序完全一致,并且所有列的排序方向(倒序或正序)都一樣時步做,MySQL才能夠使用索引來對結(jié)果做排序副渴。如果查詢需要關(guān)聯(lián)多張表奈附,則只有當(dāng)ORDER BY子句引用的字段全部為第一個表時全度,才能使用索引來做排序。ORDER BY子句和查找型查詢的限制是一樣的斥滤,需要滿足最左前綴的要求将鸵。
9 壓縮(前綴壓縮)索引
MyISAM使用前綴壓縮來減少索引的大小,從而讓更多的索引可以放入內(nèi)存中佑颇,這在某些情況下能極大地提高性能顶掉。壓縮塊使用更少的空間,代價是某些操作可能更慢挑胸。因為每個值的壓縮前綴都依賴前面的值痒筒,所以MyISAM查找時無法在索引塊使用二分查找而只能從頭開始掃描。
10 冗余和重復(fù)索引
應(yīng)避免,因為MySQL需要單獨維護重復(fù)的索引簿透,并且優(yōu)化器在優(yōu)化查詢的時候也需要逐個地進行考慮移袍,這會影響性能。
11 索引案例學(xué)習(xí)
-
1 支持多種過濾條件
考慮使用頻率老充,考慮字段選擇性葡盗,創(chuàng)建不同的組合索引,適用不同的查詢條件啡浊。
可以在索引中加入更多的列觅够,并通過IN()的方式覆蓋那些WHERE子句中的列。但這種技巧也不能濫用巷嚣,否則可能會帶來麻煩喘先。因為每額外增加一個in條件,優(yōu)化器需要做的組合都將以指數(shù)形式增加廷粒。
image.png -
2 避免多個范圍條件
image.png
image.png
image.png -
3 優(yōu)化排序
對于那些選擇性非常低的列苹祟,可以增加一些特殊的索引來做排序。
image.png