MySQL ICP(Index Condition Pushdown)特性

1、SQL的where條件提取規則

在ICP(Index Condition Pushdown,索引條件下推)特性以前,必須先搞明白根據何登成大神總結出一套放置於全部SQL語句而皆準的where查詢條件的提取規則:全部SQL的where條件,都可概括爲3大類:Index Key (First Key & Last Key),Index Filter,Table Filter。前端

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

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

Index First Keygithub

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

Index Last Keyshell

用來定位索引的終止範圍,所以對於起始範圍以後讀到的每一條索引記錄,均須要判斷是否已經超過了Index Last Key的範圍,若超過,則當前查詢結束;數據庫

Index Filter緩存

用於過濾索引查詢範圍中不知足查詢條件的記錄,所以對於索引範圍中的每一條記錄,均須要與Index Filter進行對比,若不知足Index Filter則直接丟棄,繼續讀取索引下一條記錄;性能

Table Filter測試

則是最後一道where條件的防線,用於過濾經過前面索引的層層考驗的記錄,此時的記錄已經知足了Index First Key與Index Last Key構成的範圍,而且知足Index Filter的條件,回表讀取了完整的記錄,判斷完整記錄是否知足Table Filter中的查詢條件,一樣的,若不知足,跳過當前記錄,繼續讀取索引的下一條記錄,若知足,則返回記錄,此記錄知足了where的全部條件,能夠返回給前端用戶。

2、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次數,提升查詢語句性能。

3、測試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。

4、案例分析

 

以上面的查詢爲例,關閉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 層過濾。

5、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/

相關文章
相關標籤/搜索