索引優化:如何避免索引失效?


索引失效:索引已經創建,建索引相當於給字段進行排序,如按順序建立了三個索引。而索引失效就是你建立的索引的順序用不上了,即索引建了但是沒用上。

 

 

不讓索引失效的sql就是好sql

一、 全值匹配我最愛。全值匹配即個數和順序一致

我們已經建了一個復合索引(name,age,pos,

最好最完美的sql就是你的索引怎么建的,我就怎么用。

在相同結果下,key_len越小越好。但是如果精度提高,付出的代價要大一些,即key_len更大。精度要求越來越高,花費的代價要多一些。

1、如果建了3個索引,而where后條件只用了第一個索引。索引不會失效,只是使用部分索引。

2、如果建了3個索引,而where后條件只用了前兩個索引。索引不會失效,只是使用部分索引

3、如果建了3個索引,where后條件用了全部三個個索引。索引不會失效,這即全值匹配

4、如果建了3個索引,而where后條件只用了后兩個索引。雖然能查詢出來,索引會失效

 

發現全表掃描,實際建了索引,但是沒有用到。另外ref為null,原來為const。

5、如果建了3個索引,而where后條件只用了第一個和第三個索引。雖然能查詢出來且索引不會失效,但不是全值匹配,而是使用部分索引,索引只用到了第一個即name。

6、如果建了3個索引,而where后條件只用了最后一個索引或者只用了一個中間的字段。雖然能查詢出來,索引會失效

總結:我們建立了復合索引(name,age,pos,但是如果查詢條件中沒有第一個name字段,只有單獨的age字段或者單獨的pos字段,或者只有后面兩個字段,索引會失效。違背了高效sql最重要的原則。最佳左前綴法則。

最佳左前綴法則指的是查詢從索引的最左前列開始並且不跳過索引中的列。如果索引了多列,要遵守最左前綴法則。

一、即帶頭大哥不能死。從最左開始,你建的索引的第一個字段不能丟,

二、中間兄弟不能斷。

要區分:索引失效、部分使用索引、全值匹配。

三、不在索引列上做任何操作(計算、函數、自動或手動類型轉換),會導致索引失效而轉向全表掃描。

Left是mysql自帶的函數,有點類似於java的subString函數。Left(name,4)表示從左邊開始選四位。此時在索引列name上包了一個函數。·

仍然能夠查出來,但是索引會失效。

四、存儲引擎不能使用索引中范圍條件右邊的列。

全值匹配

 

Type由ref變為了range,范圍之后的索引全失效。但是范圍本身的字段age有被用到。Age與name還有點區別:name用於了查詢,但是age只給了一個范圍,age也用到了,否則不會給range,但是age用於去排序,而不是像name一樣着重檢索(查詢),

下圖的key_len證明用到了age字段

五、盡量使用覆蓋索引(只訪問索引的查詢(索引列和查詢列一致)),減少select *

我們寫sql的原則:最好是按需取數據,用多少取多少,盡量跟索引重合。盡量少用*

沒有使用索引覆蓋。

使用*的話,共有四個字段,除了name,age,pos,還有入職時間add_time。

Using where:表示使用了where過濾,去表中檢索。

索引覆蓋了

用到了Using index,表示使用了索引覆蓋,避免了訪問表的數據行從索引中取數據,性能更加優秀,更好一些

 

部分使用索引,且索引覆蓋

 注意:ref只有一個const

范圍之后的索引會失效,Using index表示去索引上拿,key_len為74而不是78,沒有用到range,

部分使用索引,且索引覆蓋

上面的例子中,你建的索引是name,age,pos,而你查的剛好是name,age,pos,一一吻合。

而如果你只查詢索引字段的一部分,此時也會用到Using index

 部分使用索引,且進行了索引覆蓋。

六、mysql在使用不等於!=或者<><>也表示不等於)!=或者<,>的時候無法使用索引會導致全表掃描。

我們也不能為了優化而束手束腳,如果有些表數據了非常少,而且各種特殊的歷史原因或者極端的需求下面,即便索引失效了,我們也要不得已而為之。即不要為了避免索引失效而不敢寫sql,你要知道這種情況下會導致失效,但是該寫的時候也要寫。具體要看生產環境和業務,具體問題具體分析。

七、is null is not null也無法使用索引。

由於在網站注冊的時候,name不能為null。大家都知道,實在不行,關鍵字段也要寫default值等於-1或者其他,避免null值。

而對於is not null,理論上用到索引,實際上沒有用到索引。

八、like以通配符開頭(‘%ABC’),mysql索引失效會變成全表掃描的操作。使用“%July%”和“%July”雖然可以查詢出來,但是會導致索引失效而全表掃描。使用 “July”則不會導致索引失效。所以說一般寫like查詢,百分號寫在右邊。即百分like加右邊

 

百萬級別的數據量的單表必須要避免全表掃描。

一般就是在你的where語句中出現了between、<、>in、like等的查詢,type才為range。即like查詢是一個范圍。

如果生產環境中非要兩邊寫百分號,否則數據不對。如何避免能查出數據又避免索引不失效呢?

解決like “%字符串%”時索引不被使用的方法:用覆蓋索引來解決

 

建索引之前,使用like “%aa%”查詢id,name,age中的單個字段,會導致索引失效。

建索引之前,使用like “%aa%”查詢id,name,age中的兩個或三個字段,會導致索引失效。

建索引之前,使用like “%aa%”查詢id,name,ageemail中的全部字段,會導致索引失效。

結論:沒建索引之前,都是全表掃描。

用覆蓋索引來防止索引失效,從而避免全表掃描。

創建索引:假設經常要查詢name和age這兩個字段。

 

 

因為id是主鍵,它也可以從主鍵上去取。

 

 

 

 

 

 

覆蓋索引就是:你建的索引和我查的字段個數和順序完全一致。你建的索引是復合索引(name,age,

八、字符串不加單引號索引失效。如果varchar類型寫錯了,一定會被項目經理罵死,即varchar類型絕對不能忘記單引號

 

 

 

 

 

Name是varchar類型,name=2000仍然能查出結果,Mysql功能很強大,整數的2000String的2000一個是int類型,一個是varchar類型,name是varchar類型,而你寫成整數的時候,這是mysql將會在底層自動的做一次類型轉換,實現了從數字到String,從而幫你查出來。前面講過,不要在索引列上做任何操作(自動類型轉換),否則會導致索引失效。

九、少用or,用它來連接時會索引失效。注意是少用而不是不用。

小總結:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM