索引失效的幾種場景

2021-09-19 17:48:27 字數 2156 閱讀 4140

在資料庫sql優化中,百分之80%的問題sql都可以通過索引來解決,但是有時候我們也會碰到一種情況,明明索引都有,為什麼mysql沒有選擇走索引而是走了全表掃瞄呢?近期就碰到乙個案例,同大家分析乙個當時的解決思路以及對索引失效的幾種情況總結一下~

在乙個風和麗日的下午,突然一條高亮的釘釘資訊抖動在為眼前。【尊敬的使用者***,您的資料庫例項rm-aabbcc,有告警產生:mysql cpu使用率》= 90, now is 99.0,請及時處理。】吶尼!資料庫cpu報警了!!!

1、不管三七二十一,接收到報警資訊的第一反應都是立馬登入阿里雲控制管理臺,去抓問題現場!登上去後可以看到資料庫會話已經出現了堆積,所有sql的執行時間都比較長,且全部在sending data的狀態。

2、sql執行效率很差,抓取其中一條sql,登入資料庫檢視執行計畫,檢視慢究竟慢在了**,另外建議開發同學排查該sql屬於哪塊兒業務,同時我們對sql執行計畫進行分析:

從這個執行計畫中我們可以一眼看到問題,p表與s表關聯是本可以走s表的主鍵索引,但是卻選擇走了全表掃瞄,mysql為什麼會這樣做呢?mysql為什麼會認為走all的效率會很好??我們可以通過force index來強制sql走主鍵索引,看sql效率是否有提公升。

通過force index強制sql走主鍵索引進行關聯後,sql執行效率提公升顯著。所以,mysql此時預設的執行計畫是錯誤的。所以我們想要解決這個問題,必然要分析清楚為什麼索引會失效。

3、表的字符集格式以及排序方式一致,排除隱式轉換導致的索引失效。繼續往後面看,發現spu表的table_rows為0???排查到這裡問題原因基本找到,spu表的統計資訊有誤導致mysql執行計畫選擇錯誤。建議業務方先把堆積的sqlkill掉緩解資料庫的壓力。

當資料庫負載降下來後,我們再次核實一下我們的猜想是否正確,實際上該錶有50w的資料量,但是統計資訊卻是0,所以誤導mysql認為走all的效率也是很快的,而sql實際執行下來掃瞄資料量很大,sql執行效率極差。

表資料量不大,資料庫當前負載也不高,建議直接analyze table tbl_name來重新統計表資訊。

重新統計表資訊後,我們再次觀察統計資訊和執行計畫,spu的table_rows進行了更正,且執行計畫在不加force的情況下選擇走了主鍵索引進行表關聯,sql執行效率恢復正常。

以上是整個問題排查以及處理的流程,那麼究竟什麼情況會導致索引失效呢?我這邊大致想到了三種情況:

1、使用函式

where date(create_at) = '2019-01-01'
2、表關聯字符集格式以及排序方式不一致

1.關注charset和collation

2.sql寫法錯誤導致的索引失效比較常見的例子是,我們儲存手機號的字段格式為varchar,但是sql卻寫的where phone=123;

3、統計資訊不準確

本案例

MySQL索引失效的幾種場景

我們都知道建立索引能夠提高查詢效率,那麼是不是任何情況下都能提高呢,當然不是的的,下面我們就來列舉一些常見的索引失效的場景。在card code列沒加索引的時,查詢時間如下,大概都在0.07秒。我們來加上索引試試,加上後查詢效率高了許多。在正確使用索引的情況下,查詢一行資料的時間不到10毫秒,所以顯...

MySQL索引失效的幾種場景

我們來加上索引試試,加上後查詢效率高了許多。在正確使用索引的情況下,查詢一行資料的時間不到10毫秒,所以顯示0.00 sec 1.列型別是字串,查詢條件未加引號。card code列是身份證號,資料型別是varchar,在沒有將證件號碼用引號括起時不會使用索引,此時索引失效。2.未使用該列作為查詢條...

mysql 索引失效場景 Mysql 索引失效場景

例如 一張user表 有欄位屬性 name,age 其中name為索引 下面列舉幾個索引失效的情況 1.select from user where name xzz or age 16 例如這種情況 當語句中帶有or的時候 即使有索引也會失效。2.select from user where na...