MySQL 執行計劃中Extra(Using where,Using index,Using index condition,Using index,Using where...
關於如何理解SQL/">MySQL執行計劃中Extra列的Using where、Using Index、Using index condition,Using index,Using where這四者的區別。首先,我們來看看官方文件關於三者的簡單介紹(官方文件並沒有介紹Using index,Using where這種情況):
Using index (JSON property: using_index)
The column information is retrieved from the table using only information in the index tree without having to do an additional seek to read the actual row. This strategy can be used when the query uses only columns that are part of a single index.
For InnoDB tables that have a user-defined clustered index, that index can be used even when Using index is absent from the Extra column. This is the case if type is index and key is PRIMARY.
從表中僅使用索引樹中的資訊就能獲取查詢語句的列的資訊, 而不必進行其他額外查詢(seek)去讀取實際的行記錄。當查詢的列是單個索引的部分的列時, 可以使用此策略。(簡單的翻譯就是:使用索引來直接獲取列的資料,而不需回表)。對於具有使用者定義的聚集索引的 InnoDB 表, 即使從Extra列中沒有使用索引, 也可以使用該索引。如果type是index並且Key是主鍵, 則會出現這種情況。
Using where (JSON property: attached_condition)
A WHERE clause is used to restrict which rows to match against the next table or send to the client. Unless you specifically intend to fetch or examine all rows from the table, you may have something wrong in your query if the Extra value is not Using where and the table join type is ALL or index .
Using where has no direct counterpart in JSON-formatted output; the attached_condition property contains any WHERE condition used.
where 子句用於限制與下一個表匹配的行記錄或傳送到客戶端的行記錄。除非您特意打算從表中提取或檢查所有行,否則如果Extra值不是Using where並且表連線型別為ALL或index,則查詢可能會出錯。
Using index condition (JSON property: using_index_condition)
Tables are read by accessing index tuples and testing them first to determine whether to read full table rows. In this way, index information is used to defer (“push down”) reading full table rows unless it is necessary. See Section 8.2.1.5, “Index Condition Pushdown Optimization” .
在展開講述這些之前,我們先來回顧一下執行計劃中的Type與Extra部分內容。因為下面很多部分都需要這方面的知識點(其實最上面有些有關Extra的描述看起來很生澀,感覺不是那麼通熟易懂!)
Type 的相關知識點:
由左至右,效能由最差到最好
ALL:Full Table Scan, MySQL將遍歷全表以找到匹配的行
index:Full Index Scan,index與ALL區別為index型別只遍歷索引樹
range:索引範圍掃描,對索引的掃描開始於某一點,返回匹配值域的行,常見於between、<、>等的查詢
ref:非唯一性索引掃描,返回匹配某個單獨值的所有行。常見於使用非唯一索引即唯一索引的非唯一字首進行的查詢
eq_ref:唯一性索引掃描,對於每個索引鍵,表中只有一條記錄與之匹配。常見於主鍵或唯一索引掃描
const、system:當MySQL對查詢某部分進行優化,並轉換為一個常量時,使用這些型別訪問。如將主鍵置於where列表中,MySQL就能將該查詢轉換為一個常量
NULL:MySQL在優化過程中分解語句,執行時甚至不用訪問表或索引
Extra 的相關知識點:
Using temporary
表示MySQL需要使用臨時表來儲存結果集,常見於排序和分組查詢
Using filesort
MySQL中無法利用索引完成的排序操作稱為 “ 檔案排序 ”
Using Index
表示直接訪問索引就能夠獲取到所需要的資料(覆蓋索引 ) ,不需要通過索引回表;
覆蓋索引 : 如果一個索引包含(或者說覆蓋)所有需要查詢的欄位的值。我們稱之為 “ 覆蓋索引 ” 。如果索引的葉子節點中已經包含要查詢的資料,那麼還有什麼必要再回表查詢呢?
Using Index Condition
在MySQL 5.6版本後加入的新特性(Index Condition Pushdown);會先條件過濾索引,過濾完索引後找到所有符合索引條件的資料行,隨後用 WHERE 子句中的其他條件去過濾這些資料行;
Using where
表示MySQL伺服器在儲存引擎收到記錄後進行 “ 後過濾 ” (Post-filter),如果查詢未能使用索引,Using where的作用只是提醒我們MySQL將用where子句來過濾結果集。 這個一般發生在MySQL伺服器,而不是儲存引擎層 。一般發生在不能走索引掃描的情況下或者走索引掃描,但是有些查詢條件不在索引當中的情況下。
下面我們通過實驗來測試、驗證一下,並加深一下我們對這些概念的理解,測試環境資料庫為Sakila, 首先使用下面指令碼準備測試環境:
CREATE TABLE TEST( i1 INT NOT NULL DEFAULT 0, i2 INT NOT NULL DEFAULT 0, d DATE DEFAULT NULL, f INT default 0, PRIMARY KEY (i1, i2) ) ENGINE = InnoDB; INSERT INTO TEST VALUES (1, 1, '1998-01-01',1), (1, 2, '1999-01-01',2), (1, 3, '2000-01-01',1), (1, 4, '2001-01-01',2), (1, 5, '2002-01-01',1), (2, 1, '1998-01-01',2), (2, 2, '1999-01-01',1), (2, 3, '2000-01-01',2), (2, 4, '2001-01-01',1), (2, 5, '2002-01-01',2), (3, 1, '1998-01-01',1), (3, 2, '1999-01-01',2), (3, 3, '2000-01-01',1), (3, 4, '2001-01-01',2), (3, 5, '2002-01-01',1), (4, 1, '1998-01-01',2), (4, 2, '1999-01-01',1), (4, 3, '2000-01-01',2), (4, 4, '2001-01-01',1), (4, 5, '2002-01-01',2), (5, 1, '1998-01-01',1), (5, 2, '1999-01-01',2), (5, 3, '2000-01-01',1), (5, 4, '2001-01-01',2), (5, 5, '2002-01-01',1);
Extra中為Using where的情況
Extra中出現 “ Using where ” ,通常來說,意味著全表掃描或者在查詢使用索引的情況下,但是還有查詢條件不在索引欄位當中。具體來說有很多種情況,下面簡單羅列一下測試過程中遇到的各種情況(部分案例)。
1: 查詢條件中的相關列,不是索引欄位, 全表掃描後,通過Using where過濾獲取所需的資料。
通俗來說,因為欄位D沒有索引,所以必須全表掃描,然後在伺服器層使用WHERE過濾資料。
mysql> EXPLAIN -> SELECT COUNT(*) FROM TEST WHERE D = '2000-01-01'; +----+-------------+-------+------+---------------+------+---------+------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+------+---------+------+------+-------------+ | 1 | SIMPLE | TEST | ALL | NULL | NULL | NULL | NULL | 25 | Using where | +----+-------------+-------+------+---------------+------+---------+------+------+-------------+ 1 row in set (0.00 sec)
2 : (type=ref)非唯一性索引掃描,但是由於索引未覆蓋所有查詢條件(欄位d並未包含在聚集索引 PRIMARY 中 ),在儲存引擎返回記錄後,仍然需要過濾資料(排除d != '2000-01-01'的資料)。
mysql> EXPLAIN -> SELECT COUNT(*) FROM TEST WHERE i1 = 3 AND d = '2000-01-01'; +----+-------------+-------+------+---------------+---------+---------+-------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+---------+---------+-------+------+-------------+ | 1 | SIMPLE | TEST | ref | PRIMARY | PRIMARY | 4 | const | 5 | Using where | +----+-------------+-------+------+---------------+---------+---------+-------+------+-------------+ 1 row in set (0.00 sec) mysql> mysql> EXPLAIN -> SELECT * FROM TEST WHERE i1 = 3 AND d = '2000-01-01'; +----+-------------+-------+------+---------------+---------+---------+-------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+---------+---------+-------+------+-------------+ | 1 | SIMPLE | TEST | ref | PRIMARY | PRIMARY | 4 | const | 5 | Using where | +----+-------------+-------+------+---------------+---------+---------+-------+------+-------------+ 1 row in set (0.00 sec) mysql> mysql> EXPLAIN -> SELECT COUNT(i1) FROM TEST WHERE i1 = 3 AND d = '2000-01-01'; +----+-------------+-------+------+---------------+---------+---------+-------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+---------+---------+-------+------+-------------+ | 1 | SIMPLE | TEST | ref | PRIMARY | PRIMARY | 4 | const | 5 | Using where | +----+-------------+-------+------+---------------+---------+---------+-------+------+-------------+ 1 row in set (0.00 sec) mysql>
這裡即使在儲存引擎層進行非唯一性索引掃描,但是索引掃描過程中,只是過濾獲取i1=3的行記錄,相關記錄返回MySQL伺服器後,還需要對記錄進行過濾,只返回d = '2000-01-01'的記錄。簡單來說, 索引無法過濾掉無效的行。如下所示i1=3的記錄有5條,但是i1 = 3 AND d = '2000-01-01'的記錄只有一條。如下所示:
mysql> SELECT * FROM TEST WHERE i1 = 3 ; +----+----+------------+------+ | i1 | i2 | d | f | +----+----+------------+------+ | 3 | 1 | 1998-01-01 | 1 | | 3 | 2 | 1999-01-01 | 2 | | 3 | 3 | 2000-01-01 | 1 | | 3 | 4 | 2001-01-01 | 2 | | 3 | 5 | 2002-01-01 | 1 | +----+----+------------+------+ 5 rows in set (0.00 sec) mysql> SELECT * FROM TEST WHERE i1 = 3 AND d = '2000-01-01'; +----+----+------------+------+ | i1 | i2 | d | f | +----+----+------------+------+ | 3 | 3 | 2000-01-01 | 1 | +----+----+------------+------+ 1 row in set (0.00 sec) mysql>
3:WHERE篩選條件不是索引的前導列,導致不走索引,而走全表掃描。
其實此處是因為WHERE中的刷選條件不是索引的前導列,所以執行計劃走全表掃描(ALL),然後在伺服器層進行過濾資料。
mysql> EXPLAIN -> SELECT COUNT(i1) FROM TEST WHERE i2=4 AND d = '2000-01-01'; +----+-------------+-------+------+---------------+------+---------+------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+------+---------+------+------+-------------+ | 1 | SIMPLE | TEST | ALL | NULL | NULL | NULL | NULL | 25 | Using where | +----+-------------+-------+------+---------------+------+---------+------+------+-------------+ 1 row in set (0.00 sec) mysql>
注意:
Using where過濾元組和執行計劃是否走全表掃描或走索引查詢沒有關係。如上測試所示,Using where: 僅僅表示 MySQL伺服器在收到儲存引擎返回的記錄後進行 “ 後過濾 ” (Post-filter) 。 不管SQL語句的執行計劃是全表掃描(type=ALL)或非唯一性索引掃描(type=ref)。網上有種說法 “ Using where:表示優化器需要通過索引回表查詢資料" ,上面實驗可以證實這種說法完全不正確。
Extra中為Using index的情況
表示直接訪問索引就能夠獲取到所需要的資料(索引覆蓋 ) ,不需要通過索引回表。
注意:執行計劃中的Extra列的 “ Using index ” 跟type列的 “ index ” 不要混淆。Extra列的 “ Using index ” 表示索引覆蓋。而type列的 “ index ” 表示Full Index Scan。
首先,我們在表TEST上建立二級索引IX_TEST_N1
mysql> CREATE INDEX IX_TEST_N1 ON TEST(d); Query OK, 0 rows affected (0.10 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> EXPLAIN -> SELECT COUNT(*) FROM TEST WHERE D = '2000-01-01'; +----+-------------+-------+------+---------------+------------+---------+-------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+------------+---------+-------+------+-------------+ | 1 | SIMPLE | TEST | ref | IX_TEST_N1 | IX_TEST_N1 | 4 | const | 5 | Using index | +----+-------------+-------+------+---------------+------------+---------+-------+------+-------------+ 1 row in set (0.00 sec) mysql> EXPLAIN -> SELECT * FROM TEST WHERE D = '2000-01-01'; +----+-------------+-------+------+---------------+------------+---------+-------+------+-------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+------------+---------+-------+------+-------+ | 1 | SIMPLE | TEST | ref | IX_TEST_N1 | IX_TEST_N1 | 4 | const | 5 | NULL | +----+-------------+-------+------+---------------+------------+---------+-------+------+-------+ 1 row in set (0.00 sec) mysql>
如上所示,上面SQL例子中,Extra為 Using index的表示覆蓋索引,而不需回表。 而Null則表示需要回表。
mysql> EXPLAIN -> SELECT i1, i2 FROM TEST WHERE i1=3 AND i2=5; +----+-------------+-------+-------+---------------+---------+---------+-------------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+-------+---------------+---------+---------+-------------+------+-------------+ | 1 | SIMPLE | TEST | const | PRIMARY | PRIMARY | 8 | const,const | 1 | Using index | +----+-------------+-------+-------+---------------+---------+---------+-------------+------+-------------+ 1 row in set (0.00 sec) mysql> EXPLAIN -> SELECT * FROM TEST WHERE i1=3 AND i2=5; +----+-------------+-------+-------+---------------+---------+---------+-------------+------+-------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+-------+---------------+---------+---------+-------------+------+-------+ | 1 | SIMPLE | TEST | const | PRIMARY | PRIMARY | 8 | const,const | 1 | NULL | +----+-------------+-------+-------+---------------+---------+---------+-------------+------+-------+ 1 row in set (0.00 sec) mysql>
Extra中為 Using where; Using index 的情況
下面我們關閉Index Extensions選項(具體可以參考部落格MySQL索引擴充套件(Index Extensions)學習總結),那麼二級索引(Secondary Index)就不會自動補齊主鍵,將主鍵列追加到二級索引列後面,此時,Extra則會由Using index變為Using where; Using index。如下所示
mysql> EXPLAIN -> SELECT COUNT(*) FROM t1 WHERE i1 = 3 AND d = '2000-01-01'; +----+-------------+-------+------+---------------+------+---------+-------------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+------+---------+-------------+------+-------------+ | 1 | SIMPLE | t1 | ref | PRIMARY,k_d | k_d | 8 | const,const | 1 | Using index | +----+-------------+-------+------+---------------+------+---------+-------------+------+-------------+ 1 row in set (0.00 sec) mysql> SET optimizer_switch = 'use_index_extensions=off'; Query OK, 0 rows affected (0.00 sec) mysql> EXPLAIN -> SELECT COUNT(*) FROM t1 WHERE i1 = 3 AND d = '2000-01-01'; +----+-------------+-------+------+---------------+------+---------+-------+------+--------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+------+---------+-------+------+--------------------------+ | 1 | SIMPLE | t1 | ref | PRIMARY,k_d | k_d | 4 | const | 5 | Using where; Using index | +----+-------------+-------+------+---------------+------+---------+-------+------+--------------------------+ 1 row in set (0.00 sec) mysql>
這樣的細微差別,代表什麼區別呢? 我們可以理解為:MySQL伺服器在收到儲存引擎返回i1 = 3的記錄後進行 “ 後過濾 ” (Post-filter),過濾返回d = '2000-01-01'的記錄。另外,我們以樣例資料庫sakila為例, 如下所示,表rental在欄位customer_id上建有二級索引idx_fk_customer_id ,下面兩個SQL語句的執行計劃就是Using index 與Using where; Using index的區別。
mysql> EXPLAIN SELECT customer_id FROM rental WHERE customer_id=300; +----+-------------+--------+------+--------------------+--------------------+---------+-------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+--------+------+--------------------+--------------------+---------+-------+------+-------------+ | 1 | SIMPLE | rental | ref | idx_fk_customer_id | idx_fk_customer_id | 2 | const | 31 | Using index | +----+-------------+--------+------+--------------------+--------------------+---------+-------+------+-------------+ 1 row in set (0.00 sec) mysql> mysql> EXPLAIN SELECT customer_id FROM rental WHERE customer_id>=300; +----+-------------+--------+-------+--------------------+--------------------+---------+------+------+--------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+--------+-------+--------------------+--------------------+---------+------+------+--------------------------+ | 1 | SIMPLE | rental | range | idx_fk_customer_id | idx_fk_customer_id | 2 | NULL | 7910 | Using where; Using index | +----+-------------+--------+-------+--------------------+--------------------+---------+------+------+--------------------------+ 1 row in set (0.00 sec) mysql>
上面兩個SQL語句都能滿足覆蓋索引的條件,但是為什麼第二個SQL的執行計劃是 “ Using where; Using index ” 呢? 相當長的一段時間裡,即使查閱了大量關於 “ Using where; Using index ” 與 “ Using index ” 的區別的資料,但是都是霧裡看花,越糾結就越糊塗。非常讓人抓狂,而且始終沒有弄清楚到底是啥區別:
在《高效能MySQL》的相關章節,書本里面有這樣的解釋: MySQL伺服器在儲存引擎返回行以後在應用WHERE條件過濾。
摘抄一段在此,方便各位理解:
InnoDB只有在訪問行的時候才會對其加鎖,而索引能夠減少InnoDB訪問的行數,從而減少鎖的數量。但這隻有當InnoDB在儲存引擎層能夠過濾
掉所有不需要的行時才有效,如果索引無法過濾掉無效的行,那麼在InnoDB檢索到資料並返回給伺服器層以後, MySQL伺服器才能應用WHERE子句。
這時已經無法避免鎖定行了:InnoDB已經鎖定了這些行,到適當的時候才釋放。在MySQL 5.1和之後的版本中, InnoDB可以在伺服器端過濾掉行後
就釋放鎖,但是在早期的MySQL版本中,InnoDB只有在事務提交後才能釋放鎖。
是否有人看完上面這段解釋,還是有點迷惑。WHERE條件customer_id>=300 ,執行計劃使索引範圍掃描,對索引的掃描customer_id大於等於300的行,返回了所有匹配的值,這個已經是經過過濾後的資料了,不應該在伺服器使用WHERE過濾資料啊? Why??? 直到後面看了何登成大神 “ ofollow,noindex">SQL中的where條件,在資料庫中提取與應用淺析 ” 這篇文章,才基本上明白,MySQL對WHERE條件的分解和提取。簡單點理解,就是Using where; Using index 這個表示在索引的掃描過程中,也是需要過濾資料的(Index First Key 、Index Last Key),其實表掃描和索引掃描也是很類似的。只是發生的層面不一樣。個人覺得這樣的解釋已經是合理的,如有不對,敬請指教。
還有一個細節,就是你們會發現出現 “ Using where; Using index ” 意味著返回的記錄是超過一條, 而 ” Using index ” 意味著返回單條記錄,而且Type也是有所區別,從 “ ref"或eq_ref 到 ” range “ 。(這個只是簡單推測,沒有經過嚴格驗證)
注意 :不要把Extra列的"Using index"與type列的"index"搞混淆,其實這兩者完全不同,type列和覆蓋索引毫無關係,它只是表示這個查詢訪問資料的方式,或者說MySQL查詢行的方式。
Extra中為 Using index condition 的情況
Extra為Using Index Condition 表示會先條件過濾索引,過濾完索引後找到所有符合索引條件的資料行,隨後用 WHERE 子句中的其他條件去過濾這些資料行。Index Condition Pushdown (ICP)是MySQL 5.6 以上版本中的新特性,是一種在儲存引擎層使用索引過濾資料的一種優化方式。ICP開啟時的執行計劃含有 Using index condition 標示 ,表示優化器使用了ICP對資料訪問進行優化。
關於ICP的相關資料,摘抄其它部落格的兩段介紹:
a 當關閉ICP時,Index僅僅是data access的一種訪問方式,儲存引擎通過索引回表獲取的資料會傳遞到MySQL Server 層進行WHERE條件過濾。
b 當開啟ICP時,如果部分WHERE條件能使用索引中的欄位,MySQL Server 會把這部分下推到引擎層,可以利用Index過濾的WHERE條件在儲存引擎層進行資料過濾,而非將所有通過Index Access的結果傳遞到MySQL Server層進行WHERE過濾.
優化效果:ICP能減少引擎層訪問基表的次數和MySQL Server 訪問儲存引擎的次數,減少io次數,提高查詢語句效能
ICP(index condition pushdown)是MySQL利用索引(二級索引)元組和篩欄位在索引中的WHERE條件從表中提取資料記錄的一種優化操作。ICP的思想是:儲存引擎在訪問索引的時候檢查篩選欄位在索引中的WHERE條件(pushed index condition,推送的索引條件),如果索引元組中的資料不滿足推送的索引條件,那麼就過濾掉該條資料記錄。ICP(優化器)儘可能的把index condition的處理從Server層下推到Storage Engine層。Storage Engine使用索引過過濾不相關的資料,僅返回符合Index Condition條件的資料給Server層。也是說資料過濾儘可能在Storage Engine層進行,而不是返回所有資料給Server層,然後後再根據WHERE條件進行過濾。sh
下面是部落格Index Condition Pushdown中的兩幅插圖,形象的描述了使用ICP和不使用ICP,優化器的資料訪問和提取的過程。
下面我們來看看案例吧,在sakila資料庫的表rental上,在欄位`rental_date`,`inventory_id`,`customer_id`上建有唯一索引rental_date,那麼在開啟ICP時,
Extra會出現 Using index condition ,
mysql> select version(); +-----------+ | version() | +-----------+ | 5.6.41 | +-----------+ 1 row in set (0.00 sec) mysql> set optimizer_switch='index_condition_pushdown=on'; Query OK, 0 rows affected (0.00 sec) mysql> explain -> select * from rental -> where rental_date = '2006-02-14 15:16:03' -> and customer_id >= 300 -> and customer_id <= 400; +----+-------------+--------+------+--------------------------------+-------------+---------+-------+------+-----------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+--------+------+--------------------------------+-------------+---------+-------+------+-----------------------+ | 1 | SIMPLE | rental | ref | rental_date,idx_fk_customer_id | rental_date | 5 | const | 181 | Using index condition | +----+-------------+--------+------+--------------------------------+-------------+---------+-------+------+-----------------------+ 1 row in set (0.00 sec) mysql> set optimizer_switch='index_condition_pushdown=off'; Query OK, 0 rows affected (0.00 sec) mysql> explain -> select * from rental -> where rental_date = '2006-02-14 15:16:03' -> and customer_id >= 300 -> and customer_id <= 400; +----+-------------+--------+------+--------------------------------+-------------+---------+-------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+--------+------+--------------------------------+-------------+---------+-------+------+-------------+ | 1 | SIMPLE | rental | ref | rental_date,idx_fk_customer_id | rental_date | 5 | const | 181 | Using where | +----+-------------+--------+------+--------------------------------+-------------+---------+-------+------+-------------+ 1 row in set (0.00 sec) mysql>
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 優化方法。
參考資料:
https://mariadb.com/kb/en/library/index-condition-pushdown/
http://www.cnblogs.com/gomysql/p/3657395.html
https://wenku.baidu.com/view/dab46f72f46527d3240ce065.html