Index Condition Pushdown(ICP)是针对mysql使用索引从表中检索行数据时的一种优化方法。
 
在没有ICP特性之前,存储引擎根据索引去基表查找并将数据返回给mysql server,mysql server再根据where条件进行数据过滤。
有了ICP之后,在取出索引的同时,判断是否可以根据索引中的列进行where条件过滤,也就是将where的部分过滤操作放在了存储引擎层。这样就会减少上层sql层对记录的获取。
 
ICP优化支持range、ref、eq_ref、ref_or_null类型的查询。查询优化器会给出相应的提示:Using index condition。当开启ICP后,在执行计划的extra列会显示:Using index condition。
 
ICP支持innodb、myisam表。对于innodb表,ICP只是用于辅助索引。
 
在5.6中,ICP不支持分区表。这个问题在mysql 5.7中得到解决。
 
优化器使用ICP时,server层将会把能够通过使用索引进行评估的where条件下推到storage engine层。数据访问和提取过程如下:
1) storage engine从索引中读取下一条索引元组。
2) storage engine使用索引元组评估下推的索引条件。如果没有满足where条件,storage engine将会处理下一条索引元组(回到上一步)。只有当索引元组满足下推的索引条件的时候,才会继续去基表中读取数据。
3) 如果满足下推的索引条件,storage engine通过索引元组定位基表的行和读取整行数据并返回给server层。
4) server层评估没有被下推到storage engine层的where条件,如果该行数据满足where条件则使用,否则丢弃。
 
没有ICP之前:
 
开启ICP之后,就变成:
默认是开启ICP的,手动开启/关闭ICP: 
  1. set optimizer_switch = 'index_condition_pushdown=off';
  2. set optimizer_switch = 'index_condition_pushdown=on';

  

 测试过程

1.环境准备

  1. #mysql 5.6.25
  2. #关闭结果缓存
  3. mysql> set global query_cache_size=0;
  4. mysql> set query_cache_type=off;
  5.  
  6. #查看表结构
  7. mysql> show create table employees\G
  8. *************************** 1. row ***************************
  9. Table: employees
  10. Create Table: CREATE TABLE `employees` (
  11. `emp_no` int(11) NOT NULL,
  12. `birth_date` date NOT NULL,
  13. `first_name` varchar(14) NOT NULL,
  14. `last_name` varchar(16) NOT NULL,
  15. `gender` enum('M','F') NOT NULL,
  16. `hire_date` date NOT NULL,
  17. PRIMARY KEY (`emp_no`),
  18. KEY `idx_first_last_name` (`first_name`,`last_name`)
  19. ) ENGINE=InnoDB DEFAULT CHARSET=utf8
  20. 1 row in set (0.00 sec)
  21.  
  22. mysql>

2.开启ICP后进行测试

  1. mysql> set profiling = 1;
  2. mysql> select * from employees where first_name='Anneke' and last_name like '%sig' ;
  3. mysql> explain select * from employees where first_name='Anneke' and last_name like '%sig' ;
  4. mysql> show profiles;
  5. mysql> show profile cpu,block io for query 1;

3.关闭ICP后进行测试

  1. mysql> set optimizer_switch='index_condition_pushdown=off';
  2. mysql> set profiling = 1;
  3. mysql> select * from employees where first_name='Anneke' and last_name like '%sig' ;
  4. mysql> explain select * from employees where first_name='Anneke' and last_name like '%sig' ;
  5. mysql> show profiles;
  6. mysql> show profile cpu,block io for query 1;

4.结果比较

开启ICP后的执行计划:执行计划中extra部分的内容是"using index condition"

  1. mysql> explain select * from employees where first_name='Anneke' and last_name like '%sig' ;
  2. +----+-------------+-----------+------+---------------------+---------------------+---------+-------+------+-----------------------+
  3. | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
  4. +----+-------------+-----------+------+---------------------+---------------------+---------+-------+------+-----------------------+
  5. | 1 | SIMPLE | employees | ref | idx_first_last_name | idx_first_last_name | 44 | const | 224 | Using index condition |
  6. +----+-------------+-----------+------+---------------------+---------------------+---------+-------+------+-----------------------+

关闭ICP后的执行计划:执行计划中extra部分的内容是"using where"

  1. mysql> explain select * from employees where first_name='Anneke' and last_name like '%sig' ;
  2. +----+-------------+-----------+------+---------------------+---------------------+---------+-------+------+-------------+
  3. | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
  4. +----+-------------+-----------+------+---------------------+---------------------+---------+-------+------+-------------+
  5. | 1 | SIMPLE | employees | ref | idx_first_last_name | idx_first_last_name | 44 | const | 224 | Using where |
  6. +----+-------------+-----------+------+---------------------+---------------------+---------+-------+------+-------------+

 

开启ICP后的profile内容:Sending data部分的值是0.000212s

  1. mysql> show profile cpu,block io for query 1;
  2. +----------------------+----------+----------+------------+--------------+---------------+
  3. | Status | Duration | CPU_user | CPU_system | Block_ops_in | Block_ops_out |
  4. +----------------------+----------+----------+------------+--------------+---------------+
  5. | starting | 0.000114 | 0.000000 | 0.000000 | 0 | 0 |
  6. | checking permissions | 0.000007 | 0.000000 | 0.000000 | 0 | 0 |
  7. | Opening tables | 0.000018 | 0.000000 | 0.000000 | 0 | 0 |
  8. | init | 0.000034 | 0.000000 | 0.000000 | 0 | 0 |
  9. | System lock | 0.000008 | 0.000000 | 0.000000 | 0 | 0 |
  10. | optimizing | 0.000023 | 0.000000 | 0.000000 | 0 | 0 |
  11. | statistics | 0.000383 | 0.000000 | 0.000000 | 0 | 0 |
  12. | preparing | 0.000019 | 0.000000 | 0.000000 | 0 | 0 |
  13. | executing | 0.000002 | 0.000000 | 0.000000 | 0 | 0 |
  14. | Sending data | 0.000212 | 0.000000 | 0.000000 | 0 | 0 |
  15. | end | 0.000004 | 0.000000 | 0.000000 | 0 | 0 |
  16. | query end | 0.000004 | 0.000000 | 0.000000 | 0 | 0 |
  17. | closing tables | 0.000006 | 0.000000 | 0.000000 | 0 | 0 |
  18. | freeing items | 0.000020 | 0.000000 | 0.000000 | 0 | 0 |
  19. | cleaning up | 0.000011 | 0.000000 | 0.000000 | 0 | 0 |
  20. +----------------------+----------+----------+------------+--------------+---------------+

关闭ICP后的profile内容:Sending data部分的值是0.010990s

  1. mysql> show profile cpu,block io for query 1;
  2. +----------------------+----------+----------+------------+--------------+---------------+
  3. | Status | Duration | CPU_user | CPU_system | Block_ops_in | Block_ops_out |
  4. +----------------------+----------+----------+------------+--------------+---------------+
  5. | starting | 0.000165 | 0.000000 | 0.000000 | 0 | 0 |
  6. | checking permissions | 0.000022 | 0.000000 | 0.000000 | 0 | 0 |
  7. | Opening tables | 0.000027 | 0.000000 | 0.000000 | 0 | 0 |
  8. | init | 0.000039 | 0.000000 | 0.000000 | 0 | 0 |
  9. | System lock | 0.000008 | 0.000000 | 0.000000 | 0 | 0 |
  10. | optimizing | 0.000037 | 0.001000 | 0.000000 | 0 | 0 |
  11. | statistics | 0.000483 | 0.001000 | 0.000000 | 0 | 0 |
  12. | preparing | 0.000022 | 0.000000 | 0.000000 | 0 | 0 |
  13. | executing | 0.000002 | 0.000000 | 0.000000 | 0 | 0 |
  14. | Sending data | 0.010990 | 0.007999 | 0.002000 | 0 | 0 |
  15. | end | 0.000009 | 0.000000 | 0.000000 | 0 | 0 |
  16. | query end | 0.000005 | 0.000000 | 0.000000 | 0 | 0 |
  17. | closing tables | 0.000008 | 0.000000 | 0.000000 | 0 | 0 |
  18. | freeing items | 0.000028 | 0.000000 | 0.000000 | 0 | 0 |
  19. | cleaning up | 0.000014 | 0.000000 | 0.000000 | 0 | 0 |
  20. +----------------------+----------+----------+------------+--------------+---------------+

  

其它:

当sql使用覆盖索引时,不支持ICP优化方法

  1. mysql> explain select first_name,last_name from employees where first_name='Anneke' and last_name='Porenta' ;
  2. +----+-------------+-----------+------+---------------------+---------------------+---------+-------------+------+--------------------------+
  3. | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
  4. +----+-------------+-----------+------+---------------------+---------------------+---------+-------------+------+--------------------------+
  5. | 1 | SIMPLE | employees | ref | idx_first_last_name | idx_first_last_name | 94 | const,const | 1 | Using where; Using index |
  6. +----+-------------+-----------+------+---------------------+---------------------+---------+-------------+------+--------------------------+
  7. mysql> explain select * from employees where first_name='Anneke' and last_name='Porenta' ;
  8. +----+-------------+-----------+------+---------------------+---------------------+---------+-------------+------+-----------------------+
  9. | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
  10. +----+-------------+-----------+------+---------------------+---------------------+---------+-------------+------+-----------------------+
  11. | 1 | SIMPLE | employees | ref | idx_first_last_name | idx_first_last_name | 94 | const,const | 1 | Using index condition |
  12. +----+-------------+-----------+------+---------------------+---------------------+---------+-------------+------+-----------------------+

  

MySQL 5.6新特性 -- Index Condition Pushdown的更多相关文章

  1. 1229【MySQL】性能优化之 Index Condition Pushdown

    转自http://blog.itpub.net/22664653/viewspace-1210844/  [MySQL]性能优化之 Index Condition Pushdown2014-07-06 ...

  2. 【MySQL】性能优化之 Index Condition Pushdown

    一 概念介绍    Index Condition Pushdown (ICP)是MySQL 5.6 版本中的新特性,是一种在存储引擎层使用索引过滤数据的一种优化方式.a 当关闭ICP时,index ...

  3. [MySQL] 联合索引与using index condition

    1.测试联合索引的最左原则的时候, 发现了5.6版本后的新特性Index Condition Pushdown 2.含义就是存储引擎层根据索引尽可能的过滤数据,然后在返回给服务器层根据where其他条 ...

  4. MySQL ICP(Index Condition Pushdown)特性

    一.SQL的where条件提取规则 在ICP(Index Condition Pushdown,索引条件下推)特性之前,必须先搞明白根据何登成大神总结出一套放置于所有SQL语句而皆准的where查询条 ...

  5. 【mysql】关于Index Condition Pushdown特性

    ICP简介 Index Condition Pushdown (ICP) is an optimization for the case where MySQL retrieves rows from ...

  6. 浅析MySQL中的Index Condition Pushdown (ICP 索引条件下推)和Multi-Range Read(MRR 索引多范围查找)查询优化

    本文出处:http://www.cnblogs.com/wy123/p/7374078.html(保留出处并非什么原创作品权利,本人拙作还远远达不到,仅仅是为了链接到原文,因为后续对可能存在的一些错误 ...

  7. MySQL 中Index Condition Pushdown (ICP 索引条件下推)和Multi-Range Read(MRR 索引多范围查找)查询优化

    一.ICP优化原理 Index Condition Pushdown (ICP),也称为索引条件下推,体现在执行计划的上是会出现Using index condition(Extra列,当然Extra ...

  8. MySQL 之 Index Condition Pushdown(ICP)

    简介 Index Condition Pushdown (ICP)是MySQL 5.6 版本中的新特性,是一种在存储引擎层使用索引过滤数据的一种优化方式. 当关闭ICP时,index 仅仅是data ...

  9. MySQL Index Condition Pushdown

    Index Condition Pushdown (ICP)是MySQL 5.6 版本中的新特性,是一种在存储引擎层使用索引过滤数据的一种优化方式.[Index Condition Pushdown] ...

随机推荐

  1. Kylin的简介与安装部署

    一.Kylin的概述 官方网址:http://kylin.apache.org/cn/ Apache Kylin™是一个开源的分布式分析引擎,提供Hadoop/Spark之上的SQL查询接口及多维分析 ...

  2. C. 【UNR #2】黎明前的巧克力

    题解: 不会FWT,只能水40分了 首先,要观察出的性质就是: 选出的集合要满足所有数亦或等于0,而在其中任选子集都可以满足条件,答案就等于sigma(2^size(s)) 这样dp一波显然就可以O( ...

  3. python全栈开发day12-函数的有用信息、带参数的装饰器、多个装饰器装饰一个函数、global和nonlocal的进一步解析和总结

    1.上周回顾 1).函数名的应用 直接打印函数名,是函数的地址 变量 函数的参数 函数的返回值 可以当容器类数据类型的元素 2).闭包 内层函数对外层函数的非全局变量的引用,就是闭包. 并返回内部函数 ...

  4. HDU 1025 城市供应 【LIS】

    题目链接:https://vjudge.net/contest/228455#problem/A 题目大意: 有2n个城市,其中有n个富有的城市,n个贫穷的城市,其中富有的城市只在一种资源富有,且富有 ...

  5. 查找mac下腾讯视频下载地址

    mac 腾讯视频下载的视频是不可见的,也许是因为版权原因吧.使用以下方法可以在文件中找到缓存的视频(不过都是被断开的很多短视频). 在terminal输入: cd Library/Containers ...

  6. 最全的JS判断是否为中文的方法

    第一种代码:EXFCODE:1     function isChinese(temp)2     {3       var re=/[^/u4e00-/u9fa5]/;4       if (re. ...

  7. ELASTIC API

    运维常用API. curl -XGET 'localhost:9200/_cat/indices?v&pretty' #查看索引 curl -XGET 'localhost:9200/_cat ...

  8. Reactor 3 学习笔记(2)

    接上篇继续学习各种方法: 4.9.reduce/reduceWith @Test public void reduceTest() { Flux.range(1, 10).reduce((x, y) ...

  9. 让.Net程序支持命令行启动

    很多时候,我们需要让程序支持命令行启动,这个时候则需要一个命令行解析器,由于.Net BCL并没有内置命令行解析库,因此需要我们自己实现一个.对于简单的参数来说,自己写一个字符串比较函数来分析args ...

  10. asp.net mvc流程图4.6以前