时间:2021-05-24
前言
MySQL 8.0.13开始支持 index skip scan 也即索引跳跃扫描。该优化方式支持那些SQL在不符合组合索引最左前缀的原则的情况,优化器依然能组使用组合索引。
talk is cheap ,show me the code
实践
使用官方文档的例子,构造数据
mysql> CREATE TABLE t1 (f1 INT NOT NULL, f2 INT NOT NULL, PRIMARY KEY(f1, f2));Query OK, 0 rows affected (0.21 sec)mysql> INSERT INTO t1 VALUES (1,1), (1,2), (1,3), (1,4), (1,5),(2,1), (2,2), (2,3), (2,4), (2,5);Query OK, 10 rows affected (0.07 sec)Records: 10 Duplicates: 0 Warnings: 0mysql>mysql> INSERT INTO t1 SELECT f1, f2 + 5 FROM t1;Query OK, 10 rows affected (0.06 sec)Records: 10 Duplicates: 0 Warnings: 0mysql> INSERT INTO t1 SELECT f1, f2 + 10 FROM t1;Query OK, 20 rows affected (0.03 sec)Records: 20 Duplicates: 0 Warnings: 0mysql> INSERT INTO t1 SELECT f1, f2 + 20 FROM t1;Query OK, 40 rows affected (0.03 sec)Records: 40 Duplicates: 0 Warnings: 0mysql> INSERT INTO t1 SELECT f1, f2 + 40 FROM t1;Query OK, 80 rows affected (0.05 sec)Records: 80 Duplicates: 0 Warnings: 0注意t1表的主键是组合索引(f1,f2),如果sql的where条件不包含 最左前缀f1 在之前的版本中会 走 FULL TABLE SCAN,在MySQL 8.0.20版本中会是怎样呢?我们看看执行计划
mysql> EXPLAIN SELECT f1, f2 FROM t1 WHERE f2 = 40\G*************************** 1. row *************************** id: 1 select_type: SIMPLE table: t1 partitions: NULL type: rangepossible_keys: PRIMARY key: PRIMARY key_len: 8 ref: NULL rows: 16 filtered: 100.00 Extra: Using where; Using index for skip scan1 row in set, 1 warning (0.01 sec)mysql> EXPLAIN SELECT f1, f2 FROM t1 WHERE f2 > 40\G*************************** 1. row *************************** id: 1 select_type: SIMPLE table: t1 partitions: NULL type: rangepossible_keys: PRIMARY key: PRIMARY key_len: 8 ref: NULL rows: 53 filtered: 100.00 Extra: Using where; Using index for skip scan1 row in set, 1 warning (0.00 sec)两个sql 的where条件 f2>40 和 f2=40 的执行计划中都包含了Using index for skip scan 并且 type 是range 。
整个执行计划大概如下:
第一次从Index left side开始scan
第二次使用key(1,40) 扫描index,直到第一个range结束
使用key(1), find_flag =HA_READ_AFTER_KEY, 找到下一个Key值2
使用key(2,40),扫描Index, 直到range结束
使用Key(2),去找大于2的key值,上例中没有,因此结束扫描
从上述描述可以看到使用skip-scan的方式避免了全索引扫描,从而提升了性能
如果关闭 skip_scan特性,执行计划则变为type=all, extre using where 全表扫描。
mysql> set session optimizer_switch='skip_scan=off';Query OK, 0 rows affected (0.01 sec)mysql> EXPLAIN SELECT * FROM t1 WHERE f2 = 40\G*************************** 1. row *************************** id: 1 select_type: SIMPLE table: t1 partitions: NULL type: ALLpossible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 160 filtered: 10.00 Extra: Using where1 row in set, 1 warning (0.00 sec)限制条件
1.select 选择的字段不能包含非索引字段
比如c1 字段在组合索引里面 ,select * 的sql 就走不了skip scan
mysql> EXPLAIN SELECT * FROM t1 WHERE f2 = 40\G*************************** 1. row *************************** id: 1 select_type: SIMPLE table: t1 partitions: NULL type: ALLpossible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 160 filtered: 10.00 Extra: Using where1 row in set, 1 warning (0.00 sec)2.sql 中不能带 group by或者distinct 语法
mysql> EXPLAIN SELECT distinct f1 FROM t1 WHERE f2 = 40\G*************************** 1. row *************************** id: 1 select_type: SIMPLE table: t1 partitions: NULL type: rangepossible_keys: PRIMARY key: PRIMARY key_len: 8 ref: NULL rows: 3 filtered: 100.00 Extra: Using where; Using index for group-by1 row in set, 1 warning (0.01 sec)3.Skip scan仅支持单表查询,多表关联是无法使用该特性。
4.对于组合索引 ([A_1, …, A_k,] B_1, …, B_m, C [, D_1, …, D_n]),A,D 可以为空,但是B ,C 字段不能为空。
需要强调的是数据库优化没有银弹。MySQL的优化器是基于成本来选择合适的执行计划,并不是所有的忽略最左前缀的条件查询,都能利用到 index skip scan。
举个例子:
mysql> CREATE TABLE `t3` ( id int not null auto_increment PRIMARY KEY, `f1` int NOT NULL, `f2` int NOT NULL, `c1` int DEFAULT '0', key idx_f12(`f1`,`f2`,c1) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;Query OK, 0 rows affected (0.24 sec)mysql> insert into t3(f1,f2,c1) select f1,f2,c1 from t1;Query OK, 320 rows affected (0.07 sec)Records: 320 Duplicates: 0 Warnings: 0数据量增加一倍到320行记录,此时查询 f2=40 也没有利用index skip scan
mysql> explain select f2 from t3 where f2=40 \G*************************** 1. row *************************** id: 1 select_type: SIMPLE table: t3 partitions: NULL type: indexpossible_keys: idx_f12 key: idx_f12 key_len: 13 ref: NULL rows: 320 filtered: 10.00 Extra: Using where; Using index1 row in set, 1 warning (0.00 sec)-The End-
以上就是MySQL 8.0 之索引跳跃扫描(Index Skip Scan)的详细内容,更多关于MySQL 8.0 索引跳跃扫描的资料请关注其它相关文章!
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
如果MySQL正在运行,首先杀之:killall-TERMmysqld。启动MySQL:/usr/bin/safe_mysqld--skip-grant-tab
MySQL开发团队于12日宣布MySQL8.0.0开发里程碑版本(DMR)发布!可能有人会惊奇MySQL为何从5.x一下跳跃到了8.0。事实上,MySQL5.x
准备:MySQL8.0Windowszip包下载地址:https://cdn.mysql.com//Downloads/MySQL-8.0/mysql-8.0.
第一种方式:skip-grant-tables:非常有用的mysql启动参数介绍一个非常有用的mysql启动参数——--skip-grant-tables。顾名
前言MySQL8.0终于支持降序索引了。其实,从语法上,MySQL4就支持了,但正如官方文档所言,"theyareparsedbutignored",实际创建的