看到索引,应该大家都可以联想到这个是和查询效率有关系的,既然有这个功能,那么那句古话说的好啊:存在即合理。那么这个就是说有了这个功能,可以提升查询效率。
什么是索引下推
我们先有一个大概的理解:在 MySQL 中,索引下推(Index Condition Pushdown,简称 ICP)是一种优化技术,就是为了提高有索引表的查询性能。
索引下推主要的目的是:在索引扫描过程中尽可能减少回表操作(所谓回表:是指索引中返回数据行到服务器层进行进一步过滤),从而提高查询效率。
原理
没有索引下推时
在没有索引下推的情况下,存储引擎通过索引检索到数据行后,会将数据行返回给服务器层,服务器层再根据 WHERE 条件中的其他条件(非索引条件)进行过滤判断。
有索引下推时
而有了索引下推,存储引擎在检索索引的过程中,就可以根据 WHERE 条件中的其他条件对索引中包含的数据进行判断过滤,只有符合条件的数据行才会被返回给服务器层
。这样可以减少存储引擎返回给服务器层的数据行数,以及服务器层后续进行过滤判断的工作量。
这里我们看下存储引擎层和服务层的区别:
看下这个图之后,应该大家都可以理解了,执行顺序是:
总结一下哈:索引下推其实就是说,将过滤的行为传到了存储引擎层中,先在存储引擎层处理一遍,然后再返回给服务层。
为啥我感觉这个应该是理所当然的事情啊,好在这个功能现在已经是具备了。
使用场景示例
假设有一个表 users
,这里我建了一个 age 和 city 的组合索引,其结构如下:
CREATE TABLE users ( id INT PRIMARY KEY, name VARCHAR(100), age INT, city VARCHAR(100), INDEX idx_age_city (age, city)
);
如果执行以下查询:
SELECT * FROM users WHERE age BETWEEN 20 AND 30 AND city = 'New York';
在没有索引下推的情况下,MySQL 会扫描 idx_age_city
索引,找到所有 age
在 20 到 30 之间的记录,然后将这些记录返回给服务器层,服务器层再对这些记录进行 city = 'New York'
的过滤。
而在启用了索引下推的情况下,MySQL 会在存储引擎层就进行 city = 'New York'
的过滤,只有满足 age BETWEEN 20 AND 30
和 city = 'New York'
的记录才会被返回给服务器层。
如何判断是否使用了索引下推
要确认查询是否使用了索引下推,可以使用 EXPLAIN
语句来查看查询的执行计划。在执行计划中,如果使用了索引下推,会在 Extra
列中看到 Using index condition
。
EXPLAIN SELECT * FROM users WHERE age BETWEEN 20 AND 30 AND city = 'New York';
如果执行计划中的 Extra
列显示 Using index condition
,则说明该查询使用了索引下推优化。
索引下推带来的好处
- 提高查询性能
- 减少了存储引擎和服务器层之间的数据传输量,尤其是在表数据量很大、WHERE 条件比较复杂的情况下,性能提升效果更为明显。
- 降低了服务器层的 CPU 开销,因为服务器层需要处理的数据行数减少了。
- 优化复杂查询
- 对于多表连接查询,如果连接列上有索引并且可以使用索引下推,也能提高连接查询的性能。
注意事项
索引下推是 MySQL 5.6 及以上版本引入的功能,因此在较低版本的 MySQL 中无法使用。
索引下推并不能替代所有情况下的回表操作,但对于某些查询模式,它可以显著减少回表操作的次数,从而提高查询性能。
索引下推与覆盖索引(covering index)不同,覆盖索引是指索引包含了查询所需的所有列,从而避免了回表操作。索引下推则是在索引扫描过程中进行部分条件的过滤,以减少回表操作的次数。