1. 程式人生 > 其它 >索引下推,這個點你肯定不知道!

索引下推,這個點你肯定不知道!

索引下推(Index Condition Pushdown) ICP 是Mysql5.6之後新增的功能,主要的核心點就在於把資料篩選的過程放在了儲存引擎層去處理,而不是像之前一樣放到Server層去做過濾。

雖然這是一個比較簡單的概念,但是可能很多不細心的同學對於索引下推會存在一個小小的誤區,至於是什麼,請看下文。

什麼是索引下推

首先,我們建立一張user表,同時建立age_name的聯合索引,同時插入3條測試資料。

然後,我們執行查詢explain SELECT * from user where age >10 and name = 'a',如下圖所示,就會看見Extra中顯示了Using index condition

,你可能就知道了,這表示出現了索引下推了。

沒錯,針對這個查詢場景就是索引下推,那到底什麼是索引下推呢?

按照我們上述的場景,實際上就存在兩個索引樹,一個是主鍵索引,儲存了具體的資料的資訊,另外則是age_name的聯合索引,儲存了主鍵的ID。

在沒有ICP索引下推的時候,這個查詢的流程應該是這樣(略過無關的細節):

  1. Mysql Server層呼叫API查詢儲存引擎資料

  2. 儲存引擎根據聯合索引首先通過條件找到所有age>10的資料

  3. 找到的每一條資料都根據主鍵索引進行回表查詢,直到找到不符合條件的結果

  4. 返回資料給Server層,Server根據條件對結果進行過濾,流程結束

而有了ICP之後的流程則是這樣:

  1. Mysql Server層呼叫API查詢儲存引擎資料

  2. 儲存引擎根據聯合索引首先通過條件找到所有age>10的資料,根據聯合索引中已經存在的name資料進行過濾,找到符合條件的資料

  3. 根據找到符合條件的資料,回表查詢

  4. 返回資料給Server層,流程結束

對比這兩個流程就會很明顯的發現,使用ICP之後我們就是簡單的通過聯合索引中本來就有的資料直接過濾了,不需要再查到一堆無用的資料去Server層進行過濾,這樣的話減少了回表的次數和返回的資料,IO次數減少了,對效能有很好的提升。

按照官方文件所說,ICP其實也存在一定的使用限制場景,只說關鍵的,亂七八糟的不說。

  1. 首先,ICP適用於range、ref、eq_ref和ref_or_null的場景下

  2. InnoDB和MyISAM都支援ICP,Mysql partition分表的話也可以使用

  3. 對於InndoDB而言,ICP只支援二級索引,因為主鍵索引它用不上不是嗎?

  4. 子查詢不支援

現在我們基本都使用的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層進行過濾,這一點你要很明確才行。

好了,今天的話題就到這裡結束,我是艾小仙,我們下期見。

(本來我想多畫兩張圖的,不過好像覺得這個概念實在太簡單了,畫的花裡胡哨的反而沒有意義,就像你說覆蓋索引、回表還畫好幾張圖給你解釋嗎,沒有必要對不對,肯定不是因為我懶。。。)