【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 which evaluates the WHEREcondition for the rows. With ICP enabled, and if parts of the WHERE condition can be evaluated by using only fields from the index, the MySQL server pushes this part of the WHERE condition down to the storage engine. The storage engine then evaluates the pushed index condition by using the index entry and only if this is satisfied is the row read from the table. ICP can reduce the number of times the storage engine must access the base table and the number of times the MySQL server must access the storage engine.

也就说:利用索引(二级索引)来过滤一部分where条件

测试

导入数据库

wget https://launchpad.net/test-db/employees-db-1/1.0.6/+download/employees_db-full-1.0.6.tar.bz2
tar jxf employees_db-full-1.0.6.tar.bz2
cd employees_db
mysql -uroot -p < employees.sql

表结构

mysql> show create table employees \G
*************************** 1. row ***************************
       Table: employees
Create Table: CREATE TABLE `employees` (
  `emp_no` int(11) NOT NULL,
  `birth_date` date NOT NULL,
  `first_name` varchar(14) NOT NULL,
  `last_name` varchar(16) NOT NULL,
  `gender` enum(‘M‘,‘F‘) NOT NULL,
  `hire_date` date NOT NULL,
  PRIMARY KEY (`emp_no`),
  KEY `index_bh` (`birth_date`,`hire_date`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

一些表数据

mysql> select @@optimizer_switch like ‘%index_condition_pushdown%‘ \G
*************************** 1. row ***************************
@@optimizer_switch like ‘%index_condition_pushdown%‘: 1
1 row in set (0.00 sec)

mysql> select @@optimizer_switch like ‘%index_condition_pushdown%‘ \G
*************************** 1. row ***************************
@@optimizer_switch like ‘%index_condition_pushdown%‘: 1
1 row in set (0.00 sec)

mysql> select @@query_cache_type;
+--------------------+
| @@query_cache_type |
+--------------------+
| OFF                |
+--------------------+
1 row in set (0.01 sec)

mysql> select count(*) from employees;
+----------+
| count(*) |
+----------+
|   300024 |
+----------+
1 row in set (0.17 sec)

mysql> set profiling=1;
Query OK, 0 rows affected, 1 warning (0.00 sec)

建立索引

alter table employees add index index_bh (`birth_date`,`hire_date`);

查询分析

mysql> explain select *   from employees where birth_date between ‘1955-01-01‘ and ‘1955-12-31‘ and datediff(hire_date,birth_date)>12300 and first_name like ‘S%b%‘;
+----+-------------+-----------+-------+---------------+----------+---------+------+-------+-------------+
| id | select_type | table     | type  | possible_keys | key      | key_len | ref  | rows  | Extra       |
+----+-------------+-----------+-------+---------------+----------+---------+------+-------+-------------+
|  1 | SIMPLE      | employees | range | index_bh      | index_bh | 3       | NULL | 46318 | Using where |
+----+-------------+-----------+-------+---------------+----------+---------+------+-------+-------------+
1 row in set (0.00 sec)

mysql> SET optimizer_switch=‘index_condition_pushdown=on‘;
Query OK, 0 rows affected (0.00 sec)

mysql> explain select *   from employees where birth_date between ‘1955-01-01‘ and ‘1955-12-31‘ and datediff(hire_date,birth_date)>12300 and first_name like ‘S%b%‘;
+----+-------------+-----------+-------+---------------+----------+---------+------+-------+------------------------------------+
| id | select_type | table     | type  | possible_keys | key      | key_len | ref  | rows  | Extra                              |
+----+-------------+-----------+-------+---------------+----------+---------+------+-------+------------------------------------+
|  1 | SIMPLE      | employees | range | index_bh      | index_bh | 3       | NULL | 46318 | Using index condition; Using where |
+----+-------------+-----------+-------+---------------+----------+---------+------+-------+------------------------------------+
1 row in set (0.01 sec)

执行查询

mysql> show profiles;                                                                                                                 +----------+------------+------------------------------------------------------------------------------------------------------------------------------------------------------+
| Query_ID | Duration   | Query                                                                                                                                                |
+----------+------------+------------------------------------------------------------------------------------------------------------------------------------------------------+
|        1 | 0.00278025 | desc employees                                                                                                                                       |
|        2 | 0.00049775 | show create table employees                                                                                                                          |
|        3 | 0.07444550 | select *   from employees where birth_date between ‘1955-01-01‘ and ‘1955-12-31‘ and datediff(hire_date,birth_date)>12300 and first_name like ‘S%b%‘ |
|        4 | 0.00027500 | SET optimizer_switch=‘index_condition_pushdown=off‘                                                                                                  |
|        5 | 0.12347025 | select *   from employees where birth_date between ‘1955-01-01‘ and ‘1955-12-31‘ and datediff(hire_date,birth_date)>12300 and first_name like ‘S%b%‘ |
+----------+------------+------------------------------------------------------------------------------------------------------------------------------------------------------+

从结果可以看出来开启ICP之后确实快不少

启用ICP之后,可以用索引来筛选 datediff(hire_date,birth_date)>12300 记录,不需要读出整条记录

ICP原理

如下图所示(图来自MariaDB)

1、优化器没有使用ICP时

  • 在存储引擎层,首先读取索引元组(index tuple),然后使用(index tuple)在基表中(base table)定位和读取整行数据
  • 到服务器层,匹配where条件,如果该行数据满足where条件则使用,否则丢弃
  • 指针向下一行移动,重复以上过程

2、使用ICP的时候

  • 如果where条件的一部分能够通过使用索引中的字段进行过滤,那么服务器层将把这部分where条件Pushdown到存储引擎层
  • 到存储引擎层,从索引中读取索引元组(index tuple),使用索引元组进行判断,如果没有满足where条件,则处理下一条索引元组(index tuple),只有当索引元组满足条件的时候,才会去基表中读取数据

ICP的使用条件

1、只能用于二级索引(secondary index)

2、explain显示的执行计划中type值(join 类型)为range、 ref、 eq_ref或者ref_or_null。且查询需要访问表的整行数据,即不能直接通过二级索引的元组数据获得查询结果(索引覆盖)

3、ICP可以用于MyISAM和InnnoDB存储引擎,不支持分区表(5.7将会解决这个问题)

4、ICP的加速效果取决于在存储引擎内通过ICP筛选掉的数据的比例

参考文章

https://mariadb.com/kb/en/index-condition-pushdown/

http://dev.mysql.com/doc/refman/5.6/en/index-condition-pushdown-optimization.html

http://blog.codinglabs.org/articles/index-condition-pushdown.html

时间: 2024-10-08 20:37:08

【mysql】关于Index Condition Pushdown特性的相关文章

MySQL中Index Condition Pushdown(ICP)优化

在MySQL 5.6开始支持的一种根据索引进行查询的优化方式.之前的MySQL数据库版本不支持ICP,当进行索引查询是,首先根据索引来查找记录,然后在根据WHERE条件来过滤记录.在支持ICP后,MySQL数据库会在取出索引的同时,判断是否进行WHERE条件过滤,也就是将WHERE的部分过滤操作放在存储引擎层.在某些查询下,可以大大减少上层SQL层对记录的索取(fetch),从而提高整体性能 ICP优化支持range,ref,eq_ref,ref_or_null类型的查询,当前支持MyISAM和

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 ICP(Index Condition Pushdown)特性

一.SQL的where条件提取规则 在ICP(Index Condition Pushdown,索引条件下推)特性之前,必须先搞明白根据何登成大神总结出一套放置于所有SQL语句而皆准的where查询条件的提取规则:所有SQL的where条件,均可归纳为3大类:Index Key (First Key & Last Key),Index Filter,Table Filter. 接下来,简单说一下这3大类分别是如何定义,以及如何提取的,详情请看:SQL语句中where条件在数据库中提取与应用浅析.

浅析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 Index Condition Pushdown

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

【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条件在存储引擎层进

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 优化之 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