索引下推,這個點你肯定不知道!
雖然這是一個比較簡單的概念,但是可能很多不細心的同學對於索引下推會存在一個小小的誤區,至於是什麼,請看下文。
首先,我們建立一張user
表,同時建立age_name
的聯合索引,同時插入3條測試資料。
然後,我們執行查詢explain SELECT * from user where age >10 and name = 'a'
,如下圖所示,就會看見Extra
中顯示了Using index condition
沒錯,針對這個查詢場景就是索引下推,那到底什麼是索引下推呢?
按照我們上述的場景,實際上就存在兩個索引樹,一個是主鍵索引,儲存了具體的資料的資訊,另外則是age_name
的聯合索引,儲存了主鍵的ID。
在沒有ICP索引下推的時候,這個查詢的流程應該是這樣(略過無關的細節):
-
Mysql Server層呼叫API查詢儲存引擎資料
-
儲存引擎根據聯合索引首先通過條件找到所有age>10的資料
-
找到的每一條資料都根據主鍵索引進行回表查詢,直到找到不符合條件的結果
-
返回資料給Server層,Server根據條件對結果進行過濾,流程結束
而有了ICP之後的流程則是這樣:
-
Mysql Server層呼叫API查詢儲存引擎資料
-
儲存引擎根據聯合索引首先通過條件找到所有age>10的資料,根據聯合索引中已經存在的
name
資料進行過濾,找到符合條件的資料 -
根據找到符合條件的資料,回表查詢
-
返回資料給Server層,流程結束
對比這兩個流程就會很明顯的發現,使用ICP之後我們就是簡單的通過聯合索引中本來就有的資料直接過濾了,不需要再查到一堆無用的資料去Server層進行過濾,這樣的話減少了回表的次數和返回的資料,IO次數減少了,對效能有很好的提升。
按照官方文件所說,ICP其實也存在一定的使用限制場景,只說關鍵的,亂七八糟的不說。
-
首先,ICP適用於range、ref、eq_ref和ref_or_null的場景下
-
InnoDB和MyISAM都支援ICP,Mysql partition分表的話也可以使用
-
對於InndoDB而言,ICP只支援二級索引,因為主鍵索引它用不上不是嗎?
-
子查詢不支援
現在我們基本都使用的5.6以上的版本了,預設就是開啟ICP的,想關閉的話可以通過命令SET optimizer_switch = 'index_condition_pushdown=off';
。
一個小小的誤區
一般來說,正常情況下Mysql一次查詢都只能走一個索引,我們來修改上述的表結構,把聯合索引改為兩個單獨的索引,資料保持不變
然後我們執行查詢explain SELECT * from user where age >10 and name like 'a%'
,結果如下圖。
你會發現,我靠,怎麼還有索引下推?這不科學對不對,好像無法解釋嘛,難道這一次索引下推還能先查出age
再下推到name
索引嗎,這完全不合理啊。
其實不然,真實的情況是,Using index condition
並不代表一定是使用了索引下推,只是代表可以使用,但是不一定用了。。。
這個就有點坑爹,可能會對我們判斷的時候造成誤解啊。
如果你去網上搜很多人舉例子這樣建索引,然後告訴你這就是索引下推的時候,你可以盡情的噴他了,我們說索引下推一定是在聯合索引的情況下,根據聯合索引本身就有的資料直接做一次過濾,而不用再進行多次無用的回表再到Server層進行過濾,這一點你要很明確才行。
好了,今天的話題就到這裡結束,我是艾小仙,我們下期見。