转自http://blog.itpub.net/22664653/viewspace-1210844/

分类: MySQL

一 概念介绍
    Index Condition Pushdown (ICP)是MySQL 5.6 版本中的新特性,是一种在存储引擎层使用索引过滤数据的一种优化方式。
a 当关闭ICP时,index 仅仅是data access 的一种访问方式,存储引擎通过索引回表获取的数据会传递到MySQL Server 层进行where条件过滤。
b 当打开ICP时,如果部分where条件能使用索引中的字段,MySQL Server 会把这部分下推到引擎层,可以利用index过滤的where条件在存储引擎层进行数据过滤,而非将所有通过index access的结果传递到MySQL server层进行where过滤.
优化效果:ICP能减少引擎层访问基表的次数和MySQL Server 访问存储引擎的次数,减少io次数,提高查询语句性能。

二 原理
Index Condition Pushdown is not used:
  1 Get the next row, first by reading the index tuple, and then by using the index tuple to locate and read the full table row.
  2 Test the part of the WHERE condition that applies to this table. Accept or reject the row based on the test result.
Index Condition Pushdown is used
  1 Get the next row s index tuple (but not the full table row).
  2 Test the part of the WHERE condition that applies to this table and can be checked using only index columns. 
    If the condition is not satisfied, proceed to the index tuple for the next row.
  3 If the condition is satisfied, use the index tuple to locate and read the full table row.
  4 est the remaining part of the WHERE condition that applies to this table. Accept or reject the row based on the test result.

三 实践案例
a 环境准备 
   数据库版本 5.6.16
   关闭缓存
     set query_cache_size=0;
     set query_cache_type=OFF;
   测试数据下载地址 
b 当开启ICP时

  1. mysql> SET profiling = 1;
  2. Query OK, 0 rows affected, 1 warning (0.00 sec)
  3. mysql> select * from employees where first_name='Anneke' and last_name like '%sig' ;
  4. +--------+------------+------------+-----------+--------+------------+
  5. | emp_no | birth_date | first_name | last_name | gender | hire_date |
  6. +--------+------------+------------+-----------+--------+------------+
  7. | 10006  | 1953-04-20 | Anneke     | Preusig   | F      | 1989-06-02 |
  8. +--------+------------+------------+-----------+--------+------------+
  9. 1 row in set (0.00 sec)
  10. mysql> show profiles;
  11. +----------+------------+--------------------------------------------------------------------------------+
  12. | Query_ID | Duration   | Query                                                                          |
  13. +----------+------------+--------------------------------------------------------------------------------+
  14. | 1        | 0.00060275 | select * from employees where first_name='Anneke' and last_name like '%sig'    |
  15. +----------+------------+--------------------------------------------------------------------------------+
  16. 3 rows in set, 1 warning (0.00 sec)

此时情况下根据MySQL的最左前缀原则, first_name 可以使用索引,last_name采用了like 模糊查询,不能使用索引。 
c 关闭ICP

  1. mysql> set optimizer_switch='index_condition_pushdown=off';
  2. Query OK, 0 rows affected (0.00 sec)
  3. mysql> SET profiling = 1;
  4. Query OK, 0 rows affected, 1 warning (0.00 sec)
  5. mysql> select * from employees where first_name='Anneke' and last_name like '%sig' ;
  6. +--------+------------+------------+-----------+--------+------------+
  7. | emp_no | birth_date | first_name | last_name | gender | hire_date |
  8. +--------+------------+------------+-----------+--------+------------+
  9. | 10006  | 1953-04-20 | Anneke     | Preusig   | F      | 1989-06-02 |
  10. +--------+------------+------------+-----------+--------+------------+
  11. 1 row in set (0.00 sec)
  12. mysql> SET profiling = 0;
  13. Query OK, 0 rows affected, 1 warning (0.00 sec)
  14. mysql> show profiles;
  15. +----------+------------+--------------------------------------------------------------------------------+
  16. | Query_ID | Duration   | Query                                                                          |
  17. +----------+------------+--------------------------------------------------------------------------------+
  18. | 2        | 0.00097000 | select * from employees where first_name='Anneke' and last_name like '%sig'    |
  19. +----------+------------+--------------------------------------------------------------------------------+
  20. 6 rows in set, 1 warning (0.00 sec)

当开启ICP时 查询在sending data环节时间消耗是 0.000189s

  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.000094 | 0.000000 | 0.000000   | 0            | 0             |
  6. | checking permissions | 0.000011 | 0.000000 | 0.000000   | 0            | 0             |
  7. | Opening tables       | 0.000025 | 0.000000 | 0.000000   | 0            | 0             |
  8. | init                 | 0.000044 | 0.000000 | 0.000000   | 0            | 0             |
  9. | System lock          | 0.000014 | 0.000000 | 0.000000   | 0            | 0             |
  10. | optimizing           | 0.000021 | 0.000000 | 0.000000   | 0            | 0             |
  11. | statistics           | 0.000093 | 0.000000 | 0.000000   | 0            | 0             |
  12. | preparing            | 0.000024 | 0.000000 | 0.000000   | 0            | 0             |
  13. | executing            | 0.000006 | 0.000000 | 0.000000   | 0            | 0             |
  14. | Sending data         | 0.000189 | 0.000000 | 0.000000   | 0            | 0             |
  15. | end                  | 0.000019 | 0.000000 | 0.000000   | 0            | 0             |
  16. | query end            | 0.000012 | 0.000000 | 0.000000   | 0            | 0             |
  17. | closing tables       | 0.000013 | 0.000000 | 0.000000   | 0            | 0             |
  18. | freeing items        | 0.000034 | 0.000000 | 0.000000   | 0            | 0             |
  19. | cleaning up          | 0.000007 | 0.000000 | 0.000000   | 0            | 0             |
  20. +----------------------+----------+----------+------------+--------------+---------------+
  21. 15 rows in set, 1 warning (0.00 sec)

当关闭ICP时 查询在sending data环节时间消耗是 0.000735s

  1. mysql> show profile cpu,block io for query 2;
  2. +----------------------+----------+----------+------------+--------------+---------------+
  3. | Status               | Duration | CPU_user | CPU_system | Block_ops_in | Block_ops_out |
  4. +----------------------+----------+----------+------------+--------------+---------------+
  5. | starting             | 0.000045 | 0.000000 | 0.000000   | 0            | 0             |
  6. | checking permissions | 0.000007 | 0.000000 | 0.000000   | 0            | 0             |
  7. | Opening tables       | 0.000015 | 0.000000 | 0.000000   | 0            | 0             |
  8. | init                 | 0.000024 | 0.000000 | 0.000000   | 0            | 0             |
  9. | System lock          | 0.000009 | 0.000000 | 0.000000   | 0            | 0             |
  10. | optimizing           | 0.000012 | 0.000000 | 0.000000   | 0            | 0             |
  11. | statistics           | 0.000049 | 0.000000 | 0.000000   | 0            | 0             |
  12. | preparing            | 0.000016 | 0.000000 | 0.000000   | 0            | 0             |
  13. | executing            | 0.000005 | 0.000000 | 0.000000   | 0            | 0             |
  14. | Sending data         | 0.000735 | 0.001000 | 0.000000   | 0            | 0             |
  15. | end                  | 0.000008 | 0.000000 | 0.000000   | 0            | 0             |
  16. | query end            | 0.000008 | 0.000000 | 0.000000   | 0            | 0             |
  17. | closing tables       | 0.000009 | 0.000000 | 0.000000   | 0            | 0             |
  18. | freeing items        | 0.000023 | 0.000000 | 0.000000   | 0            | 0             |
  19. | cleaning up          | 0.000007 | 0.000000 | 0.000000   | 0            | 0             |
  20. +----------------------+----------+----------+------------+--------------+---------------+
  21. 15 rows in set, 1 warning (0.00 sec)

从上面的profile 可以看出ICP 开启时整个sql 执行时间是未开启的2/3,sending data 环节的时间消耗前者仅是后者的1/4。

ICP 开启时的执行计划 含有 Using index condition 标示 ,表示优化器使用了ICP对数据访问进行优化。

  1. mysql> explain select * from employees where first_name='Anneke' and last_name like '%nta' ;
  2. +----+-------------+-----------+------+---------------+--------------+---------+-------+------+-----------------------+
  3. | id | select_type | table     | type | possible_keys | key          | key_len | ref   | rows | Extra                 |
  4. +----+-------------+-----------+------+---------------+--------------+---------+-------+------+-----------------------+
  5. | 1  | SIMPLE      | employees | ref  | idx_emp_fnln  | idx_emp_fnln | 44      | const | 224  | Using index condition |
  6. +----+-------------+-----------+------+---------------+--------------+---------+-------+------+-----------------------+
  7. 1 row in set (0.00 sec)

ICP 关闭时的执行计划显示use where.

  1. mysql> explain select * from employees where first_name='Anneke' and last_name like '%nta' ;
  2. +----+-------------+-----------+------+---------------+--------------+---------+-------+------+-------------+
  3. | id | select_type | table     | type | possible_keys | key          | key_len | ref   | rows | Extra       |
  4. +----+-------------+-----------+------+---------------+--------------+---------+-------+------+-------------+
  5. | 1  | SIMPLE      | employees | ref  | idx_emp_fnln  | idx_emp_fnln | 44      | const | 224  | Using where |
  6. +----+-------------+-----------+------+---------------+--------------+---------+-------+------+-------------+
  7. 1 row in set (0.00 sec)

案例分析
以上面的查询为例关闭ICP 时,存储引擎通前缀index first_name 访问表中225条first_name 为Anneke的数据,并在MySQL server层根据last_name like '%sig' 进行过滤
开启ICP 时,last_name 的like '%sig'条件可以通过索引字段last_name 进行过滤,在存储引擎内部通过与where条件的对比,直接过滤掉不符合条件的数据。该过程不回表,只访问符合条件的1条记录并返回给MySQL Server ,有效的减少了io访问和各层之间的交互。

ICP 关闭时 ,仅仅使用索引作为访问数据的方式。

ICP 开启时 ,MySQL将在存储引擎层 利用索引过滤数据,减少不必要的回表,注意 虚线的using where 表示如果where条件中含有没有被索引的字段,则还是要经过MySQL Server 层过滤。

四 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 5.6 版本的不支持分表的ICP 功能,5.7 版本的开始支持。
7 当sql 使用覆盖索引时,不支持ICP 优化方法。

  1. mysql> explain select * 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_emp_fnln  | idx_emp_fnln | 94      | const,const | 1    | Using index condition |
  6. +----+-------------+-----------+------+---------------+--------------+---------+-------------+------+-----------------------+
  7. 1 row in set (0.00 sec)
  8. mysql> explain select first_name,last_name from employees where first_name='Anneke' and last_name='Porenta' ;
  9. +----+-------------+-----------+------+---------------+--------------+---------+-------------+------+--------------------------+
  10. | id | select_type | table     | type | possible_keys | key          | key_len | ref         | rows | Extra                    |
  11. +----+-------------+-----------+------+---------------+--------------+---------+-------------+------+--------------------------+
  12. | 1  | SIMPLE      | employees | ref  | idx_emp_fnln  | idx_emp_fnln | 94      | const,const | 1    | Using where; Using index |
  13. +----+-------------+-----------+------+---------------+--------------+---------+-------------+------+--------------------------+

1229【MySQL】性能优化之 Index Condition Pushdown的更多相关文章

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

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

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

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

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

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

  4. MySQL 优化之 ICP (index condition pushdown:索引条件下推)

    ICP技术是在MySQL5.6中引入的一种索引优化技术.它能减少在使用 二级索引 过滤where条件时的回表次数 和 减少MySQL server层和引擎层的交互次数.在索引组织表中,使用二级索引进行 ...

  5. MySQL 5.6 中一个重要的优化——Index Condition Pushdown,究竟push down了什么

    1        问题描述 一条SQL,在数据库中是如何执行的呢?相信很多人都会对这个问题比较感兴趣.当然,要完整描述一条SQL在数据库中的生命周期,这是一个非常巨大的问题,涵盖了SQL的词法解析.语 ...

  6. MySQL索引与Index Condition Pushdown

    实际上,这个页面所讲述的是在MariaDB 5.3.3(MySQL是在5.6)开始引入的一种叫做Index Condition Pushdown(以下简称ICP)的查询优化方式.由于本身不是一个层面的 ...

  7. MySQL ICP(Index Condition Pushdown)特性

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

  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. 随机记录工作中常见的sql用法错误(一)

    没事开始写博客,留下以前工作中常用的笔记,内容不全或者需要补充的可以留言,我只写我常用的. 网上很多类似动软生成器的小工具,这类工具虽然在表关系复杂的时候没什么软用,但是在一些简单的表结构关系还是很方 ...

  2. 对 Serializable和Parcelable理解

    1.首先他们两个接口都是为了实现对象的序列化,使之可以传递,所谓序列化就是将对象信息装换成可以存储的介质的过程. 2.Serializable是jdk所提供的序列化接口,该接口存在于io包下,可想用于 ...

  3. Hibernate关联映射 映射文件的配置

    一:多对一单向关联 首先我们必须创建两个实体类 例如:Dept类 public class Dept { private Integer deptNo; private String dName; p ...

  4. 关于mysql字段时间类型timestamp默认值为当前时间问题

    今天把应用部署到AWS上发现后台修改内容提交后程序报错,经过排查发现是更新数据的时候,有张数据表中的一个timestamp类型的字段默认值变成了"0000-00-00 00:00:00.00 ...

  5. session 存入数据库 php

     session 机制 1.php中session的生成机制 session是保存在服务器的,当我们在代码中调用session_start();时,PHP会同时往SESSION的存放目录(默认为/tm ...

  6. js类型转换

    1.js中有六种基本类型,分别是object.number.string.Boolean.null.undefined,其中number.string.Boolean为基本类型,有时使用会强制转换成对 ...

  7. Android游戏开发实践(1)之NDK与JNI开发02

    Android游戏开发实践(1)之NDK与JNI开发02 承接上篇Android游戏开发实践(1)之NDK与JNI开发01分享完JNI的基础和简要开发流程之后,再来分享下在Android环境下的JNI ...

  8. yii2实战教程之新手入门指南-简单博客管理系统

    作者:白狼 出处:http://www.manks.top/document/easy_blog_manage_system.html 本文版权归作者,欢迎转载,但未经作者同意必须保留此段声明,且在文 ...

  9. 从Sql Server表中随机获取一些记录最简单的方法

    * FROM test ORDER BY NewID() 注意,使用时,请将‘test’改为真实的表名.

  10. Hibernate 系列 07 - Hibernate中Java对象的三种状态

    引导目录: Hibernate 系列教程 目录 1. Java对象的三种状态 当应用通过调用Hibernate API与框架发生交互时,需要从持久化的角度关注应用对象的生命周期. 持久化声明周期是Hi ...