一 概述
日常處理mysql問題中,往往通過增加索引來提高查詢速度,但在有些情況下,執行過程中並沒有按照我們的預期結果執行,也就是說,即使欄位加了索引,但現實也沒有使用到,到底是什麼地方出了差錯,以下我們將一**竟。
二 實驗表結構宣告:
我們將對以下表結構進行實際案例分析
三 mysql不走索引歸類以及詳細解析根據實驗表做具體case分析,歸納為以下幾點:createtable `student` (
`id` int(11) not null auto_increment,
`age` int(11) default 0,
`name` varchar(16) default "",
key idx_age (`age`),
key idx_name (`name`),
primary key (`id`)
) engine=innodb;
1. 查詢條件在索引列上使用函式操作,或者運算的情況
例如以下case是不走索引的:
2. 查詢條件字串和數字之間的隱式轉換例如:name與age分別做字串/數字(88)的隱式轉換;explain select * from student where abs(age) =18;
explain select * from student where age + 1=18;
以下case走索引情況:
以下case不走索引情況:explain select * from student where name =』88』;
explain select * from student where age='88';
explain select * from student where age =88;
explain select * from student where name=88;
3. 特殊修飾符 %%, or 將不走索引
4. 索引優化器選擇最優的索引這一點最重要,索引到底用不用,不是列加了索引就一定會用,而是根據索引優化器來決定。explain select * from student where name like'%name%' ;
explain select * from student where name ='name' or age = 18;
索引優化器的存在,就是找到乙個索引掃瞄行數最少的方案去執行語句。那麼掃瞄行數怎麼來判斷的?是逐行統計資料表的資料嗎?其實並不是,而是根據統計資訊來估算的值。這個統計資訊就是我們常說的索引的「區分度」。
顯然,乙個索引上不同的值越多,這個索引的區分度就越好。我們把乙個索引上不同的值的個數,稱之為「索引基數」。也就是說,基數越大,索引的區分度就越好,執行查詢的行數就越少。如何檢視索引基數呢?使用 show index from 表名,cardinality欄位顯示的就是索引的基數。
擴充套件:mysql 是怎樣得到索引基數的呢?不感興趣的小夥伴可以飄過啦。
索引基數 = 取樣統計*頁數。取樣統計就是避免把整張表取出來一行行統計做精準計算,以免消耗系統效能。在取樣統計時,innodb缺省會選擇 n 個資料頁,統計這些頁面上的不同值,得到乙個平均值,然後乘以這個索引的頁面數,就得到了這個索引的基數。統計資訊不是固定不變的,他會隨著資料表的變化而變化。當變更的資料行數超過 1/m 的時候,會自動觸發重新做一次索引統計。
索引優化器例項一:
經常聽人說,執行<>語句時,不走索引,今天我們將看一看實際執**況,還是那句話,到底走不走,我們說了不算,還是索引優化器說了算:
看截圖 ,就會發現 <> 其實是走了索引。
為什麼會出現這樣的情景呢?因為 student表中10w多條資料的值全都是'name',索引基數太小,所以在執行<>'1name'查詢時,實際上要查詢條數為10多w條,如果走了name欄位索引,其實和全表查詢沒什麼區別,況且,執行name欄位索引,最終還是要轉換為主鍵索引(二級索引查詢都會轉換為主鍵查詢),所以索引優化器的優化結果是不走name索引。然而在執行<>'name'查詢時,優化器優化結果是走name索引,因為,<>'name'的查詢行數很小,大部分條數name欄位的值都是'name'。
索引優化器例項二:
同理,字首like匹配是走索引,但是,以下卻展示了不一樣的結果:
為什麼會這樣呢?請小夥伴們參考例項一仔細思考一下。
如何指定優化器執行固定的索引:
索引優化器的存在,我們就沒辦法指定強制走我們指定的索引?
答案就是通過 force index強制來實現,執行語句和分析結果如下圖所示
四 總結以及實際應用
實際應用中,應該牢記上述索引優化的原則,比如在實際工作中,由於索引優化器選錯索引,導致資料查詢緩慢,阻塞線上業務,而當時的解決辦法,就是上述文章的分析過程,以及採用force 強制索引才解決的,前車之鑑,希望廣大讀者避免踩坑。
用心,就一定會幸福
一直覺得,自己不是乙個幸福的人。面對太美好的事物,反而容易擔心,這是做夢吧?怎麼可能有這樣的幸運降臨到自己身上呢?要不然就會想,是不是很快就會消失了呢?然而,要命的完美主義又讓我無法輕易地得過且過 生命於是變成了一場詭計,它安排我去追逐乙個又乙個可能一輩子也無法實現的夢,在過程中我還不斷的檢視自己,...
探索索引的奧秘 有索引就一定會用麼?
索引設定為unusable,會有以下特點,1.索引設定為unusable,此時會刪除索引段。2.索引處於unusable期間,對錶資料做dml操作,此時不維護索引。3.索引處於unusable期間,優化器會忽略此索引。4.索引處於unusable期間,由於不需要維護索引,因此可以提公升批量匯入效能。...
MqSql一定一定會索引失效的幾種情況
使用explain查詢 檢視key是否命中索引 1.表層面,兩個表關聯時,如果兩個表關聯欄位的的編碼不同,不會走索引。如乙個表時 utf8,另外乙個表是utf8mb4 2.like查詢是以 開頭,索引不會命中,放後面會命中 3.如果查詢時,查詢的字段型別沒有寫對,底層會隱式處理加上函式,不會命中 4...