万答#20,索引下推如何进行数据过滤

2022-01-18  本文已影响0人  GreatSQL
  • GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源。

实验环境

GreatSQL 8.0.25 InnoDB

1.索引下推介绍

2.适用条件

3.如何启用

# 关闭ICP
SET optimizer_switch = 'index_condition_pushdown=off'; 
# 开启ICP
SET optimizer_switch = 'index_condition_pushdown=on';
# 查看ICP当前状态
show VARIABLES like '%optimizer_switch%'

4.ICP 如何工作

不使用 ICP 优化时的查询步骤

使用 ICP 优化时的查询步骤

5.实验测试

表结构如下

CREATE TABLE `student` (
  `id` int NOT NULL AUTO_INCREMENT COMMENT '自增id',
  `uid` int NOT NULL COMMENT '学号',
  `age` int NOT NULL COMMENT '年龄',
  `name` char(32) NOT NULL COMMENT '姓名',
  `sex` char(4) NOT NULL COMMENT '性别',
  `grade` int NOT NULL COMMENT '年级',
  `class` varchar(32) NOT NULL COMMENT '班级',
  `major` varchar(64) NOT NULL COMMENT '专业',
  PRIMARY KEY (`id`),
  KEY `idx_anm` (`age`,`name`,`major`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci 

现有一个需求,查询年龄16、姓陈、学习软件工程的同学信息

# 启用ICP
[root@GreatSQL][test]>explain select * from student where age=16 and name like '陈%' and major='软件工程';
+----+-------------+---------+------------+-------+---------------+---------+---------+------+------+----------+-----------------------+
| id | select_type | table   | partitions | type  | possible_keys | key     | key_len | ref  | rows | filtered | Extra                 |
+----+-------------+---------+------------+-------+---------------+---------+---------+------+------+----------+-----------------------+
|  1 | SIMPLE      | student | NULL       | range | idx_anm       | idx_anm | 390     | NULL |    1 |    33.33 | Using index condition |
+----+-------------+---------+------------+-------+---------------+---------+---------+------+------+----------+-----------------------+
1 row in set, 1 warning (0.00 sec)

# 不启用ICP
[root@GreatSQL][test]>explain select /*+ no_icp (student) */ * from student where age=16 and name like '陈%' and major='软件工程';
+----+-------------+---------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
| id | select_type | table   | partitions | type  | possible_keys | key     | key_len | ref  | rows | filtered | Extra       |
+----+-------------+---------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | student | NULL       | range | idx_anm       | idx_anm | 390     | NULL |    1 |    33.33 | Using where |
+----+-------------+---------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

启用 ICP 解析出来的 Extra 是 Using index condition ,不启用 ICP 解析出来的 Extra 是 Using where

其他查询结果基本一样,看不出有效率差别,可以通过开启profiling进行查看

[root@GreatSQL][test]>set profiling=1;
Query OK, 0 rows affected, 1 warning (0.00 sec)

[root@GreatSQL][test]>select * from student where age=16 and name like '陈%' and major='软件工程';
+----+--------+-----+--------+-----+-------+-------+--------------+
| id | uid    | age | name   | sex | grade | class | major        |
+----+--------+-----+--------+-----+-------+-------+--------------+
|  1 | 100001 |  16 | 陈红   | 男  |     4 | 3     | 软件工程     |
+----+--------+-----+--------+-----+-------+-------+--------------+
1 row in set (0.00 sec)

(Tue Jan  4 15:51:50 2022)[root@GreatSQL][test]>select /*+ no_icp (student) */ * from student where age=16 and name like '陈%' and major='软件工程';
+----+--------+-----+--------+-----+-------+-------+--------------+
| id | uid    | age | name   | sex | grade | class | major        |
+----+--------+-----+--------+-----+-------+-------+--------------+
|  1 | 100001 |  16 | 陈红   | 男  |     4 | 3     | 软件工程     |
+----+--------+-----+--------+-----+-------+-------+--------------+
1 row in set (0.00 sec)

[root@GreatSQL][test]>show profiles\G;
*************************** 1. row ***************************
Query_ID: 1
Duration: 0.00043725
   Query: select * from student where age=16 and name like '陈%' and major='软件工程'
*************************** 2. row ***************************
Query_ID: 2
Duration: 0.00048500
   Query: select /*+ no_icp (student) */ * from student where age=16 and name like '陈%' and major='软件工程'
2 rows in set, 1 warning (0.00 sec)

ERROR:
No query specified

使用了 ICP 的 Duration 要比没有使用的时间稍短一些,多次测试效率对比结果都一样,从测试来看,使用 ICP 优化的查询效率会好一些。

6.查询流程

没有开启 ICP

1.根据最左原则先找到 age=16 的记录,然后回表,根据主键找出满足记录的行。

2.然后找出所有符合like '陈%'的行记录,然后再根据步骤1查出来的数据,根据主键过滤符合条件的记录

3.然后找出所有符合 major='软件工程' 再根据步骤2查出所有符合条件的记录

4.步骤1查询过程,每个符合 age=16 的记录都要先进行回表操作。

开启 ICP

1.根据最左原则先找到 age=16 的记录。

2.查看索引过滤掉不符合 like '陈%' 的数据

3.查看索引过滤掉不符合 major='软件工程' 的数据

4.步骤1查询过程,先不进行回表操作,先通过索引找出符合2、3条件的情况,如何不符合则直接进行下一个步骤查询,故回表次数会少一些。

7.ICP 图解

图1:没有启用ICP查询过程


file

图2:启用ICP查询过程


file

说明:图2的几个X是由于在索引层就进行数据过滤了,故不需要再进行回表。

8.更多内容查看官网

Enjoy GreatSQL :)

本文由博客一文多发平台 OpenWrite 发布!

上一篇 下一篇

猜你喜欢

热点阅读