前些天發現了一個巨牛的人工智能學習網站,通俗易懂,風趣幽默,忍不住分享一下給大家。點選跳轉到網站。
MySQL查詢導緻索引失效的情況有很多,通過搜尋引擎搜尋MySQL索引失效 幾乎都會提到一個情況,那就是like查詢以“%”開頭。但是 LIKE查詢 以%開頭一定會讓索引失效嗎?
驗證準備
- 建立一張users表,表結構如下,表中有999999條資料:
- 在name字段上建立索引
驗證階段
要驗證一段SQL語句有沒有使用到索引,最好的方法莫過于使用SQL執行計劃EXPLAIN了。
- 首先先看一下LIKE查詢不以%開頭的情況:
EXPLAIN SELECT * FROM users WHERE `name` LIKE '001%';
type=range,key=idx_name,說明這段是使用了索引的。
-
接着再看一下LIKE查詢不以%開頭的情況
先看第一段SQL語句:
EXPLAIN SELECT * FROM users WHERE `name` LIKE '%001%'
type=ALL,是以這段SQL是沒有使用索引的。
再來看第二段SQL語句:
EXPLAIN SELECT `name` FROM users WHERE `name` LIKE '%001%';
type=index,key=idx_name,這個結果說明這段SQL是使用了索引的。
接着看第三段SQL語句:
EXPLAIN SELECT id , `name` FROM users WHERE `name` LIKE '%001%';
第三段SQL語句是在第二段SQL語句的基礎上多查詢一列id。這個執行結果和第二段是一樣的,說明這段也是使用了索引的。
最後看一下第四段SQL語句:
EXPLAIN SELECT id , `name` , gender FROM users WHERE `name` LIKE '%001%';
第四段SQL語句是在第三段SQL語句的基礎上多查詢兩列id和gender。執行結果和第一段一樣,是沒有使用索引的。
驗證結果
通過以上驗證可以發現,LIKE查詢 以%開頭不一定會讓索引失效。
為什麼會走索引呢?
首先解釋一下,執行計劃中type=ALL和index。還有key的含義。
- type=ALL:全表掃描,周遊整張表去查詢比對的結果,不走索引。
- type=index:使用索引覆寫,僅僅掃描索引樹,比ALL要快。
- type=range:使用索引進行範圍查詢時就會用到range通路方法。
- key:實際使用到的索引,如果為NULL就是沒使用索引。
LIKE查詢以%開頭使用了索引的原因就是使用了索引覆寫。
針對二級索引MySQL提供了一個優化技術。即從輔助索引中就可以得到查詢的記錄,就不需要回表再根據聚集索引查詢一次完整記錄。使用索引覆寫的一個好處是輔助索引不包含整行記錄的所有資訊,故其大小要遠小于聚集索引,是以可以減少大量的IO操作,但是前提是要查詢的所有列必須都加了索引。
LIKE查詢以%開頭會導緻全索引掃描或者全表掃描,如果沒有索引覆寫的話,查詢到的資料會回表,多了一次IO操作,當MySQL預估全表掃描或全索引掃描的時間比走索引花費的時間更少時,就不會走索引。有了索引覆寫就不需要回表了,減少了IO操作,花費的時間更少,是以就使用了索引。