GreatSQL 8.0.25 InnoDB
# 关闭ICP SET optimizer_switch = 'index_condition_pushdown=off'; # 开启ICP SET optimizer_switch = 'index_condition_pushdown=on'; # 查看ICP当前状态 show VARIABLES like '%optimizer_switch%'
不使用 ICP 优化时的查询步骤
使用 ICP 优化时的查询步骤
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 优化的查询效率会好一些。
没有开启 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条件的情况,如何不符合则直接进行下一个步骤查询,故回表次数会少一些。
图1:没有启用ICP查询过程
图2:启用ICP查询过程
说明:图2的几个X是由于在索引层就进行数据过滤了,故不需要再进行回表。
Enjoy GreatSQL :)