MySQL ICP(Index Condition Pushdown)特性


一、SQL的where條件提取規則

在ICP(Index Condition Pushdown,索引條件下推)特性之前,必須先搞明白根據何登成大神總結出一套放置於所有SQL語句而皆准的where查詢條件的提取規則:所有SQL的where條件,均可歸納為3大類:Index Key (First Key & Last Key),Index Filter,Table Filter。

接下來,簡單說一下這3大類分別是如何定義,以及如何提取的,詳情請看:SQL語句中where條件在數據庫中提取與應用淺析

Index Key(Fist key & Last Key),Index Filter,Table Filter

Index First Key

只是用來定位索引的起始范圍,因此只在索引第一次Search Path(沿着索引B+樹的根節點一直遍歷,到索引正確的葉節點位置)時使用,一次判斷即可;

Index Last Key

用來定位索引的終止范圍,因此對於起始范圍之后讀到的每一條索引記錄,均需要判斷是否已經超過了Index Last Key的范圍,若超過,則當前查詢結束;

Index Filter

用於過濾索引查詢范圍中不滿足查詢條件的記錄,因此對於索引范圍中的每一條記錄,均需要與Index Filter進行對比,若不滿足Index Filter則直接丟棄,繼續讀取索引下一條記錄;

Table Filter

則是最后一道where條件的防線,用於過濾通過前面索引的層層考驗的記錄,此時的記錄已經滿足了Index First Key與Index Last Key構成的范圍,並且滿足Index Filter的條件,回表讀取了完整的記錄,判斷完整記錄是否滿足Table Filter中的查詢條件,同樣的,若不滿足,跳過當前記錄,繼續讀取索引的下一條記錄,若滿足,則返回記錄,此記錄滿足了where的所有條件,可以返回給前端用戶。

二、ICP特性介紹

Index Condition Pushdown (ICP)是MySQL 5.6版本中的新特性,是一種在存儲引擎層使用索引過濾數據的一種優化方式。

我對Using index condition的理解是,首先mysql server和storage engine是兩個組件,server負責sql的parse,執行; storage engine去真正的做數據/index的讀取/寫入。以前是這樣:server命令storage engine按index key把相應的數據從數據表讀出,傳給server,然后server來按where條件(index filter和table filter)做選擇。

而在MySQL 5.6加入ICP后,Index Filter與Table Filter分離,Index Filter下降到InnoDB的索引層面進行過濾,如果不符合條件則無須讀數據表,減少了回表與返回MySQL Server層的記錄交互開銷,節省了disk IO,提高了SQL的執行效率。

原理

a. 當關閉ICP時,index僅僅是data access的一種訪問方式,存儲引擎通過索引回表獲取的數據會傳遞到MySQL Server層進行where條件過濾,也就是做index filter和table filter。

b. 當打開ICP時,如果部分where條件能使用索引中的字段,MySQL Server會把這部分下推到引擎層,可以利用index filter的where條件在存儲引擎層進行數據過濾,而非將所有通過index access的結果傳遞到MySQL server層進行where過濾。

優化效果:ICP能減少引擎層訪問基表的次數和MySQL Server訪問存儲引擎的次數,減少io次數,提高查詢語句性能。

三、測試ICP優化SQL

本文選用MySQL官方文檔中提供的示例數據庫之一:employees。這個數據庫關系復雜度適中,且數據量較大。下圖是這個數據庫的E-R關系圖(引用自MySQL官方手冊):

MySQL ICP(Index Condition Pushdown)特性

MySQL官方文檔中關於此數據庫的頁面為:https://dev.mysql.com/doc/employee/en,里面詳細介紹了此數據庫,並提供了下載地址和導入方法,如果有興趣導入此數據庫到自己的MySQL可以參考文中內容。

可以選擇下載測試數據:https://github.com/datacharmer/test_db

關閉緩存(最好關閉后重啟MySQL)

 導入employees庫,需要自己手動創建一個聯合索引。 

其表結構如下:

當開啟ICP時(默認開啟)

此時情況下根據MySQL的最左前綴原則,irst_name 可以使用索引,last_name采用了like 模糊查詢,不能使用索引。

當關閉ICP時

當開啟ICP時,查詢在sending data環節時間消耗是 0.00108900s

當關閉ICP時,查詢在sending data環節時間消耗是 0.00231650s

從上面的profile可以看出ICP開啟時整個sql 執行時間是未開啟的2/3,sending data 環節的時間消耗前者僅是后者的1/4。

ICP 開啟時的執行計划 含有 Using index condition 標示 ,表示優化器使用了ICP對數據訪問進行優化。ICP關閉時的執行計划顯示use where。

四、案例分析

 

以上面的查詢為例,關閉ICP時,存儲引擎通前綴index first_name(視為index key)訪問表中數據,並在MySQL server層根據where條件last_name like ‘%nta’(視為index filter)進行過濾。

開啟ICP時,MySQL server把index filter(last_name like ‘%nta’)推到存儲引擎層,在存儲引擎內部通過與where條件last_name like ‘%nta’的對比,直接過濾掉不符合條件的數據,然后返回最終數據給MySQL server層。該過程減少了回表操作,只訪問符合條件的1條記錄並返回給MySQL Server ,有效的減少了io訪問和各層之間的交互。

ICP關閉時 ,僅僅使用索引作為訪問數據的方式。

MySQL ICP(Index Condition Pushdown)特性

ICP 開啟時 ,MySQL將在存儲引擎層 利用索引過濾數據,減少不必要的回表。

MySQL ICP(Index Condition Pushdown)特性

注意虛線的using where表示如果where條件中含有沒有被索引的字段,則還是要經過MySQL Server 層過濾。

五、ICP的使用限制

1. 當sql需要全表訪問時,ICP的優化策略可用於range, ref, eq_ref, ref_or_null類型的訪問數據方法 。

2. 支持InnoDB和MyISAM表。

3. ICP只能用於二級索引,不能用於主索引。

4. 並非全部where條件都可以用ICP篩選,如果where條件的字段不在索引列中,還是要讀取整表的記錄到server端做where過濾。

5. ICP的加速效果取決於在存儲引擎內通過ICP篩選掉的數據的比例。

6. MySQL 5.6版本的不支持分表的ICP功能,5.7版本的開始支持。

7. 當sql使用覆蓋索引時,不支持ICP優化方法。

  

原文鏈接:http://blog.itpub.net/22664653/viewspace-1210844/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM