mysql (ICP) 索引條件下推對比ORACLE進行說明

yuntui發表於2015-12-14
mysql (ICP) 索引條件下推對比ORACLE進行說明<br /> <br /> <br /> 第一次看到這個名詞,與ORACLE FPD - filter push-down想到了一塊,但是後來才發現他們根本同一個東西,<br /> 簡單的收ICP就是當索引包含所有的訪問欄位的時候,可以在根據前導列過濾掉條件的時候,同時過濾掉另外的<br /> 條件,比如說<br /> CREATE TABLE TESTICP(A INT,B INT,C NAME);<br /> ALTER TABLE TESTTICP ADD KEY(A,B);<br /> <br /> <br /> SELECT * FROM TESTICP WHERE A=1 AND B &lt;10<br /> 的時候,如果未使用ICP就是透過A=1的條件返回結果集然後透過<br /> 回表操作後然後過濾掉B&lt;10的條件,這種情況下額外的並不滿足B&lt;10的結果集透過回表操作,這樣加大了離散<br /> 讀的壓力,如果瞭解ORACLE的朋友一定記得CLUSTER_FACTOR這個概念,他用於描述索引相對錶中資料的有序<br /> 程度,其最大值為表的行數,最小值為表的塊數,越小代表索引和表的資料越相似,也就是表中這列是比較有序的<br /> ,如果越大那麼回表的操作越耗時(離散讀取越厲害),這點雖然在MYSQL還不太瞭解但是一定會受到這樣的影響。<br /> 所以及早的過濾掉不需要的資料是非常必要的。在ORACLE中這也許不是問題,但是MYSQL知道5.6才引入了ICP。<br /> 我們先來看看ORACLE的執行計劃<br /> 使用指令碼:<br /> CREATE TABLE TESTICP(A INT,B INT,C varchar2(20));<br /> declare &nbsp;<br /> &nbsp; &nbsp;i number(10);<br /> begin&nbsp;<br /> &nbsp; for i in 1..1000<br /> &nbsp; loop<br /> &nbsp; insert into TESTICP<br /> &nbsp; &nbsp;values(i,i,'gaopeng');<br /> &nbsp; end loop;<br /> end;<br /> SELECT * FROM TESTICP WHERE A=1 AND B &lt;10;<br /> <br /> <br /> --------------------------------------------------------------------------------<br /> Plan hash value: 446810821<br /> --------------------------------------------------------------------------------<br /> | Id &nbsp;| Operation &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | Name &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;| Rows &nbsp;| Bytes | Cost (%CPU<br /> --------------------------------------------------------------------------------<br /> | &nbsp; 0 | SELECT STATEMENT &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;| &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | &nbsp; &nbsp; 1 | &nbsp; &nbsp;38 | &nbsp; &nbsp; 3 &nbsp; (0<br /> | &nbsp; 1 | &nbsp;TABLE ACCESS BY INDEX ROWID| TESTICP &nbsp; &nbsp; &nbsp; | &nbsp; &nbsp; 1 | &nbsp; &nbsp;38 | &nbsp; &nbsp; 3 &nbsp; (0<br /> |* &nbsp;2 | &nbsp; INDEX RANGE SCAN &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;| TESTICP_INDEX | &nbsp; &nbsp; 1 | &nbsp; &nbsp; &nbsp; | &nbsp; &nbsp; 2 &nbsp; (0<br /> --------------------------------------------------------------------------------<br /> Predicate Information (identified by operation id):<br /> ---------------------------------------------------<br /> &nbsp; &nbsp;2 - access("A"=1 AND "B"&lt;10)<br /> <br /> <br /> 非常加單我們只需要看到access("A"=1 AND "B"=1)就知道是透過"A"=1 AND "B"=1來訪問索引的<br /> 如果是FILTER B=1我們可以理解為訪問索引後過濾的。<br /> SQL&gt; explain plan for select * from testicp where a=1 and c='gtest';<br /> Explained<br /> <br /> <br /> SQL&gt; select * from table(dbms_xplan.display);<br /> PLAN_TABLE_OUTPUT<br /> --------------------------------------------------------------------------------<br /> Plan hash value: 446810821<br /> --------------------------------------------------------------------------------<br /> | Id &nbsp;| Operation &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | Name &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;| Rows &nbsp;| Bytes | Cost (%CPU<br /> --------------------------------------------------------------------------------<br /> | &nbsp; 0 | SELECT STATEMENT &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;| &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | &nbsp; &nbsp; 1 | &nbsp; &nbsp;38 | &nbsp; &nbsp; 3 &nbsp; (0<br /> |* &nbsp;1 | &nbsp;TABLE ACCESS BY INDEX ROWID| TESTICP &nbsp; &nbsp; &nbsp; | &nbsp; &nbsp; 1 | &nbsp; &nbsp;38 | &nbsp; &nbsp; 3 &nbsp; (0<br /> |* &nbsp;2 | &nbsp; INDEX RANGE SCAN &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;| TESTICP_INDEX | &nbsp; &nbsp; 1 | &nbsp; &nbsp; &nbsp; | &nbsp; &nbsp; 2 &nbsp; (0<br /> --------------------------------------------------------------------------------<br /> Predicate Information (identified by operation id):<br /> ---------------------------------------------------<br /> &nbsp; &nbsp;1 - filter("C"='gtest')<br /> &nbsp; &nbsp;2 - access("A"=1)<br /> Note<br /> -----<br /> &nbsp; &nbsp;- dynamic sampling used for this statement (level=2)<br /> 19 rows selected<br /> <br /> <br /> 如果我們改變為and c='gtest'<br /> 可以看到 filter("C"='gtest'),這就是所謂的過濾。是索引回表後過濾的。<br /> <br /> <br /> 但這一切在ORACLE認為理所當然的東西到了MYSQL到了5.6才實現。我們透過MYSQL來做一下<br /> 指令碼使用:<br /> <br /> <br /> <br /> <br /> create table testicp(A INT,B INT,C varchar(20));<br /> delimiter //<br /> create procedure myproc3()&nbsp;<br /> begin&nbsp;<br /> declare num int;&nbsp;<br /> set num=1;&nbsp;<br /> while num &lt;= 1000 do&nbsp;<br /> &nbsp; insert into testicp &nbsp;values(num,num,'gaopeng');&nbsp;<br /> &nbsp; set num=num+1;<br /> end while;<br /> &nbsp;end//<br /> &nbsp;call myproc3() //<br /> &nbsp;delimiter ;<br /> &nbsp;alter table testicp add key(a,b);<br /> &nbsp;<br /> explain select * from testicp where a=1 and b&lt;10;<br /> &nbsp;mysql&gt; explain select * from testicp where a=1 and b&lt;10;<br /> +----+-------------+---------+-------+---------------+------+---------+------+------+-----------------------+<br /> | id | select_type | table &nbsp; | type &nbsp;| possible_keys | key &nbsp;| key_len | ref &nbsp;| rows | Extra &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; |<br /> +----+-------------+---------+-------+---------------+------+---------+------+------+-----------------------+<br /> | &nbsp;1 | SIMPLE &nbsp; &nbsp; &nbsp;| testicp | range | A &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | A &nbsp; &nbsp;| 10 &nbsp; &nbsp; &nbsp;| NULL | &nbsp; &nbsp;1 | Using index condition |<br /> +----+-------------+---------+-------+---------------+------+---------+------+------+-----------------------+<br /> 這裡使用關鍵字Using index condition加以說明,他受引數<br /> optimizer_switch='index_condition_pushdown=on'&nbsp;<br /> 影響,如果我們設定optimizer_switch='index_condition_pushdown=off'再來看一下<br /> set &nbsp;optimizer_switch='index_condition_pushdown=off'<br /> mysql&gt; explain select * from testicp where a=1 and b&lt;10;<br /> +----+-------------+---------+-------+---------------+------+---------+------+------+-------------+<br /> | id | select_type | table &nbsp; | type &nbsp;| possible_keys | key &nbsp;| key_len | ref &nbsp;| rows | Extra &nbsp; &nbsp; &nbsp; |<br /> +----+-------------+---------+-------+---------------+------+---------+------+------+-------------+<br /> | &nbsp;1 | SIMPLE &nbsp; &nbsp; &nbsp;| testicp | range | A &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | A &nbsp; &nbsp;| 10 &nbsp; &nbsp; &nbsp;| NULL | &nbsp; &nbsp;1 | Using where |<br /> +----+-------------+---------+-------+---------------+------+---------+------+------+-------------+<br /> 1 row in set (0.01 sec)<br /> 可以看到這裡變成了Using where,這代表沒有使用icp。<br />

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/30633755/viewspace-1871648/,如需轉載,請註明出處,否則將追究法律責任。

相關文章