ITPub博客

首页 > 数据库 > MySQL > mysql (ICP) 索引条件下推对比ORACLE进行说明

mysql (ICP) 索引条件下推对比ORACLE进行说明

MySQL 作者:yuntui 时间:2015-12-14 05:35:05 0 删除 编辑
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博客 ” ,链接:https://blog.itpub.net/30633755/viewspace-1871648/ ,如需转载,请注明出处,否则将追究法律责任。

上一篇: 没有了~
请登录后发表评论 登录
全部评论

注册时间:2015-12-14

  • 博文量
    150
  • 访问量
    70807