MySQL Index Condition Pushdown

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

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

  • 实践案例

当开启ICP时

mysql> SET profiling = 1;
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> select * from employees where first_name=‘Anneke‘ and last_name like ‘%sig‘ ;
+--------+------------+------------+-----------+--------+------------+
| emp_no | birth_date | first_name | last_name | gender | hire_date |
+--------+------------+------------+-----------+--------+------------+
| 10006  | 1953-04-20 | Anneke     | Preusig   | F      | 1989-06-02 |
+--------+------------+------------+-----------+--------+------------+
1 row in set (0.00 sec)
mysql> show profiles;
+----------+------------+--------------------------------------------------------------------------------+
| Query_ID | Duration   | Query                                                                          |
+----------+------------+--------------------------------------------------------------------------------+
| 1        | 0.00060275 | select * from employees where first_name=‘Anneke‘ and last_name like ‘%sig‘    |
+----------+------------+--------------------------------------------------------------------------------+
3 rows in set, 1 warning (0.00 sec)
mysql> show profile cpu,block io for query 1;
+----------------------+----------+----------+------------+--------------+---------------+
| Status               | Duration | CPU_user | CPU_system | Block_ops_in | Block_ops_out |
+----------------------+----------+----------+------------+--------------+---------------+
| starting             | 0.000094 | 0.000000 | 0.000000   | 0            | 0             |
| checking permissions | 0.000011 | 0.000000 | 0.000000   | 0            | 0             |
| Opening tables       | 0.000025 | 0.000000 | 0.000000   | 0            | 0             |
| init                 | 0.000044 | 0.000000 | 0.000000   | 0            | 0             |
| System lock          | 0.000014 | 0.000000 | 0.000000   | 0            | 0             |
| optimizing           | 0.000021 | 0.000000 | 0.000000   | 0            | 0             |
| statistics           | 0.000093 | 0.000000 | 0.000000   | 0            | 0             |
| preparing            | 0.000024 | 0.000000 | 0.000000   | 0            | 0             |
| executing            | 0.000006 | 0.000000 | 0.000000   | 0            | 0             |
| Sending data         | 0.000189 | 0.000000 | 0.000000   | 0            | 0             |
| end                  | 0.000019 | 0.000000 | 0.000000   | 0            | 0             |
| query end            | 0.000012 | 0.000000 | 0.000000   | 0            | 0             |
| closing tables       | 0.000013 | 0.000000 | 0.000000   | 0            | 0             |
| freeing items        | 0.000034 | 0.000000 | 0.000000   | 0            | 0             |
| cleaning up          | 0.000007 | 0.000000 | 0.000000   | 0            | 0             |
+----------------------+----------+----------+------------+--------------+---------------+
15 rows in set, 1 warning (0.00 sec)

当关闭ICP时

实践案例

mysql> set optimizer_switch=‘index_condition_pushdown=off‘;
Query OK, 0 rows affected (0.00 sec)
mysql> SET profiling = 1;
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> select * from employees where first_name=‘Anneke‘ and last_name like ‘%sig‘ ;
+--------+------------+------------+-----------+--------+------------+
| emp_no | birth_date | first_name | last_name | gender | hire_date |
+--------+------------+------------+-----------+--------+------------+
| 10006  | 1953-04-20 | Anneke     | Preusig   | F      | 1989-06-02 |
+--------+------------+------------+-----------+--------+------------+
1 row in set (0.00 sec)
mysql> SET profiling = 0;
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> show profiles;
+----------+------------+--------------------------------------------------------------------------------+
| Query_ID | Duration   | Query                                                                          |
+----------+------------+--------------------------------------------------------------------------------+
| 2        | 0.00097000 | select * from employees where first_name=‘Anneke‘ and last_name like ‘%sig‘    |
+----------+------------+--------------------------------------------------------------------------------+
6 rows in set, 1 warning (0.00 sec)
mysql> show profile cpu,block io for query 2;
+----------------------+----------+----------+------------+--------------+---------------+
| Status               | Duration | CPU_user | CPU_system | Block_ops_in | Block_ops_out |
+----------------------+----------+----------+------------+--------------+---------------+
| starting             | 0.000045 | 0.000000 | 0.000000   | 0            | 0             |
| checking permissions | 0.000007 | 0.000000 | 0.000000   | 0            | 0             |
| Opening tables       | 0.000015 | 0.000000 | 0.000000   | 0            | 0             |
| init                 | 0.000024 | 0.000000 | 0.000000   | 0            | 0             |
| System lock          | 0.000009 | 0.000000 | 0.000000   | 0            | 0             |
| optimizing           | 0.000012 | 0.000000 | 0.000000   | 0            | 0             |
| statistics           | 0.000049 | 0.000000 | 0.000000   | 0            | 0             |
| preparing            | 0.000016 | 0.000000 | 0.000000   | 0            | 0             |
| executing            | 0.000005 | 0.000000 | 0.000000   | 0            | 0             |
| Sending data         | 0.000735 | 0.001000 | 0.000000   | 0            | 0             |
| end                  | 0.000008 | 0.000000 | 0.000000   | 0            | 0             |
| query end            | 0.000008 | 0.000000 | 0.000000   | 0            | 0             |
| closing tables       | 0.000009 | 0.000000 | 0.000000   | 0            | 0             |
| freeing items        | 0.000023 | 0.000000 | 0.000000   | 0            | 0             |
| cleaning up          | 0.000007 | 0.000000 | 0.000000   | 0            | 0             |
+----------------------+----------+----------+------------+--------------+---------------+
15 rows in set, 1 warning (0.00 sec)

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

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

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

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

mysql> explain select * from employees where first_name=‘Anneke‘ and last_name like ‘%nta‘ ;
+----+-------------+-----------+------+---------------+--------------+---------+-------+------+-------------+
| id | select_type | table     | type | possible_keys | key          | key_len | ref   | rows | Extra       |
+----+-------------+-----------+------+---------------+--------------+---------+-------+------+-------------+
| 1  | SIMPLE      | employees | ref  | idx_emp_fnln  | idx_emp_fnln | 44      | const | 224  | Using where |
+----+-------------+-----------+------+---------------+--------------+---------+-------+------+-------------+
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的使用限制
  1. 当sql需要全表访问时,ICP的优化策略可用于range, ref, eq_ref, ref_or_null 类型的访问数据方法 。
  2. 支持InnoDB和MyISAM表。
  3. ICP只能用于二级索引,不能用于主索引。
  4. 并非全部where条件都可以用ICP筛选。
  5. 如果where条件的字段不在索引列中,还是要读取整表的记录到server端做where过滤。
  6. ICP的加速效果取决于在存储引擎内通过ICP筛选掉的数据的比例。
  7. 5.6 版本的不支持分表的ICP 功能,5.7 版本的开始支持。
  8. 当sql 使用覆盖索引时,不支持ICP 优化方法。
mysql> explain select * from employees where first_name=‘Anneke‘ and last_name=‘Porenta‘ ;
+----+-------------+-----------+------+---------------+--------------+---------+-------------+------+-----------------------+
| id | select_type | table     | type | possible_keys | key          | key_len | ref         | rows | Extra                 |
+----+-------------+-----------+------+---------------+--------------+---------+-------------+------+-----------------------+
| 1  | SIMPLE | employees      | ref  | idx_emp_fnln  | idx_emp_fnln | 94      | const,const | 1    | Using index condition |
+----+-------------+-----------+------+---------------+--------------+---------+-------------+------+-----------------------+
1 row in set (0.00 sec)
mysql> explain select first_name,last_name from employees where first_name=‘Anneke‘ and last_name=‘Porenta‘ ;
+----+-------------+-----------+------+---------------+--------------+---------+-------------+------+--------------------------+
| id | select_type | table     | type | possible_keys | key          | key_len | ref         | rows | Extra                    |
+----+-------------+-----------+------+---------------+--------------+---------+-------------+------+--------------------------+
| 1  | SIMPLE      | employees | ref  | idx_emp_fnln  | idx_emp_fnln | 94      | const,const | 1    | Using where; Using index |
+----+-------------+-----------+------+---------------+--------------+---------+-------------+------+--------------------------+
1 row in set (0.00 sec)

  

  

时间: 2024-10-10 10:16:17

MySQL Index Condition Pushdown的相关文章

MySQL Index Condition Pushdown(ICP)优化

Index Condition Pushdown(ICP)索引条件下推优化适用于mysql在table中通过index检索数据行,没有ICP,存储引擎层遍历索引来定位基表(base table)上的数据行并且把它们返回给server层,由server层来计算过滤where语句.使用ICP,并且where语句的部分筛选条件可以通过index来检测,则mysql server层会讲部分where 条件下推给存储引擎层.存储引擎通过使用index条目来评估下推的index condition,并且仅仅

【mysql】关于Index Condition Pushdown特性

ICP简介 Index Condition Pushdown (ICP) is an optimization for the case where MySQL retrieves rows from a table using an index. Without ICP, the storage engine traverses the index to locate rows in the base table and returns them to the MySQL server whi

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

本文出处:http://www.cnblogs.com/wy123/p/7374078.html(保留出处并非什么原创作品权利,本人拙作还远远达不到,仅仅是为了链接到原文,因为后续对可能存在的一些错误进行修正或补充,无他) ICP优化原理 Index Condition Pushdown (ICP),也称为索引条件下推,体现在执行计划的上是会出现Using index condition(Extra列,当然Extra列的信息太多了,只能做简单分析)ICP原理通俗讲就是,查询过程中,直接在查询引擎

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

ICP技术是在MySQL5.6中引入的一种索引优化技术.它能减少在使用 二级索引 过滤where条件时的回表次数 和 减少MySQL server层和引擎层的交互次数.在索引组织表中,使用二级索引进行回表的代价相比堆表中是要高一些的.相关文档地址:http://dev.mysql.com/doc/refman/5.6/en/index-condition-pushdown-optimization.html Index Condition Pushdown optimization is use

MySQL索引与Index Condition Pushdown

大约在两年前,我写了一篇关于MySQL索引的文章.最近有同学在文章的评论中对文章的内容提出质疑,质疑主要集中在联合索引的使用方式上.在那篇文章中,我说明联合索引是将各个索引字段做字符串连接后作为key,使用时将整体做前缀匹配. 而这名同学在这个页面找到了如下一句话:index condition pushdown is usually useful with multi-column indexes: the first component(s) is what index access is

MySQL 5.6引入的Index Condition Pushdown浅析

1.问题描述 一条SQL,在数据库中是如何执行的呢?相信很多人都会对这个问题比较感兴趣.当然,要完整描述一条SQL在数据库中的生命周期,这是一个非常巨大的问题,涵盖了SQL的词法解析.语法解析.权限检查.查询优化.SQL执行等一系列的步骤,简短的篇幅是绝对无能为力的.因此,本文挑选了其中的部分内容,也是我一直都想写的一个内容,做重点介绍: 给定一条SQL,如何提取其中的where条件?where条件中的每个子条件,在SQL执行的过程中有分别起着什么样的作用? 通过本文的介绍,希望读者能够更好地理

MySQL 5.6新特性 -- Index Condition Pushdown

Index Condition Pushdown(ICP)是针对mysql使用索引从表中检索行数据时的一种优化方法. 在没有ICP特性之前,存储引擎根据索引去基表查找并将数据返回给mysql server,mysql server再根据where条件进行数据过滤. 有了ICP之后,在取出索引的同时,判断是否可以根据索引中的列进行where条件过滤,也就是将where的部分过滤操作放在了存储引擎层.这样就会减少上层sql层对记录的获取. ICP优化支持range.ref.eq_ref.ref_or

MySQL 索引条件下推 Index Condition Pushdown

MySQL 索引条件下推 Index Condition Pushdown 出现在MySQL5.6及之后的版本中,能大幅提升查询效率,原因如下: 内容摘录自<深入理解MariaDB和MySQL> 下面使实验,使用官方提供的employees 测试数据库演示. > use employees ; > show create table employees \G ***************************[ 1. row ]*************************

【MySQL】性能优化之 Index Condition Pushdown

一 概念介绍    Index Condition Pushdown (ICP)是MySQL 5.6 版本中的新特性,是一种在存储引擎层使用索引过滤数据的一种优化方式.a 当关闭ICP时,index 仅仅是data access 的一种访问方式,存储引擎通过索引回表获取的数据会传递到MySQL Server 层进行where条件过滤.b 当打开ICP时,如果部分where条件能使用索引中的字段,MySQL Server 会把这部分下推到引擎层,可以利用index过滤的where条件在存储引擎层进