索引条件下推(index condition pushdown)

索引条件下推(index condition pushdown)

概念

​ 当没有icp时,存储引擎会运用索引定位到符合索引条件的行,将这些行发送给MySQL server去计算where 条件是否正确。当有icp时,如果where 条件的一部分可以通过索引来计算(意思就是索引中包含的信息可以计算这一部分where条件),那么MySQL Server就会将这部分索引条件下推到(index condition push)存储引擎(下推的意思可以看MySQL逻辑架构图)去计算,这样的话就可以返回尽量少的行给MySQL Server,也尽量少的让MySQL Server访问存储引擎层。

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 WHERE condition for the rows. With ICP enabled, and if parts of the WHERE condition can be evaluated by using only columns 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.

——官方原文

​ 使用索引下推的标志是explain的extra列中显示了Using index condition。

打开和关闭索引条件下推

SET optimizer_switch = 'index_condition_pushdown=off'; 

SET optimizer_switch = 'index_condition_pushdown=on';

例子

例子1:有一个联合索引(a,b,c),当查询where a=x and c=x2,根据最左匹配原则,只有a会用得上,对于c不同版本就有区别了:

  1. 在MySQL5.6之前,就是根据二级索引找出每一条a=x的叶子节点的主键,然后拿着主键去回表,根据回表拿到对应行c的值,将不符合c=x2的行过滤掉
  2. 在MySQL5.6引入了索引下推优化,找到a=x后,因为在二级索引中就有c的值了,MySQL Server 就会将c=x2这个索引条件下推给存储引擎去做,所以在二级索引内就判断该行是否符合c=x2,不符合直接就跳过了,这样就少了很多次回表

例子2(官方给的例子):

Suppose that a table contains information about people and their addresses and that the table has an index defined as INDEX (zipcode, lastname, firstname). If we know a person’s zipcode value but are not sure about the last name, we can search like this:

SELECT * FROM people
  WHERE zipcode='95054'
  AND lastname LIKE '%etrunia%'
  AND address LIKE '%Main Street%';

MySQL can use the index to scan through people with zipcode='95054'. The second part (lastname LIKE '%etrunia%') cannot be used to limit the number of rows that must be scanned, so without Index Condition Pushdown, this query must retrieve full table rows for all people who have zipcode='95054'.

With Index Condition Pushdown, MySQL checks the lastname LIKE '%etrunia%' part before reading the full table row. This avoids reading full rows corresponding to index tuples that match the zipcode condition but not the lastname condition.

假设一个包含人们信息和他们的地址的表,并且这个表包含了index(zipcode,lastname,firstname)定义的表。如果我们知道一个人的zipcode但不确定他的lastname,我们就可以像这样一样搜索

select * from people
  where zipcode = '95054'
    and lastname like '%entrunia%'
    and address like '%Main Street%';

MySQL可以使用索引扫描zipcode='95054’的人。但是第二部分(lastname like ‘%etrunia%’)不能被使用(不符合最左匹配原则)用来限制必须被扫描的行的数量,所以没有icp的话,这个查询必须检索所有zipcode='95054’的人的整个数据行。

使用icp的话,MySQL会在读取整个数据行之前判断’lastname like ‘%etrunia%’’ 部分。这避免了读取 ‘可以使用zipcode 条件但不可以使用lastname条件’ 的索引项对应的整个数据行。

发布了44 篇原创文章 · 获赞 12 · 访问量 2万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章