干货 | 解读MySQL 8.0新特性:Skip Scan Range
MySQL从8.0.13版本开始支持一种新的range scan方式,称为Loose Skip Scan。该特性由Facebook贡献。我们知道在之前的版本中,如果要使用到索引进行扫描,条件必须满足索引前缀列,比如索引idx(col1,col2), 如果where条件只包含col2的话,是无法有效的使用idx的, 它需要扫描索引上所有的行,然后再根据col2上的条件过滤。
新的优化可以避免全量索引扫描,而是根据每个col1上的值+col2上的条件,启动多次range scan。每次range scan根据构建的key值直接在索引上定位,直接忽略了那些不满足条件的记录。
示例
下例是从官方文档上摘取的例子:
root@test 11:03:28>CREATE TABLE t1 (f1 INT NOT NULL, f2 INT NOT NULL, PRIMARY KEY(f1, f2));
Query OK, 0 rows affected (0.00 sec)
root@test 11:03:29>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.00 sec)
Records: 10 Duplicates: 0 Warnings: 0
root@test 11:03:29>INSERT INTO t1 SELECT f1, f2 + 5 FROM t1;
Query OK, 10 rows affected (0.00 sec)
Records: 10 Duplicates: 0 Warnings: 0
root@test 11:03:29>INSERT INTO t1 SELECT f1, f2 + 10 FROM t1;
Query OK, 20 rows affected (0.00 sec)
Records: 20 Duplicates: 0 Warnings: 0
root@test 11:03:29>INSERT INTO t1 SELECT f1, f2 + 20 FROM t1;
Query OK, 40 rows affected (0.00 sec)
Records: 40 Duplicates: 0 Warnings: 0
root@test 11:03:29>INSERT INTO t1 SELECT f1, f2 + 40 FROM t1;
Query OK, 80 rows affected (0.00 sec)
Records: 80 Duplicates: 0 Warnings: 0
root@test 11:03:29>ANALYZE TABLE t1;
+---------+---------+----------+----------+
| Table | Op | Msg_type | Msg_text |
+---------+---------+----------+----------+
| test.t1 | analyze | status | OK |
+---------+---------+----------+----------+
1 row in set (0.00 sec)
root@test 11:03:29>EXPLAIN SELECT f1, f2 FROM t1 WHERE f2 > 40;
+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+----------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+----------------------------------------+
| 1 | SIMPLE | t1 | NULL | range | PRIMARY | PRIMARY | 8 | NULL | 53 | 100.00 | Using where; Using index for skip scan |
+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+----------------------------------------+
1 row in set, 1 warning (0.00 sec)
也可以从optimizer trace里看到如何选择的skip scan:
"skip_scan_range": {
"potential_skip_scan_indexes": [
{
"index": "PRIMARY",
"tree_travel_cost": 0.4,
"num_groups": 3,
"rows": 53,
"cost": 10.625
}
]
},
"best_skip_scan_summary": {
"type": "skip_scan",
"index": "PRIMARY",
"key_parts_used_for_access": [
"f1",
"f2"
],
"range": [
"40 < f2"
],
"chosen": true
},
我们从innodb的角度来看看这个SQL是如何执行的,我们知道每个index scan都会走到ha_innobase::index_read来构建search tuple,上述查询的执行步骤:
- 第一次从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值,上例中没有,因此结束扫描
笔者在代码注入了日志,打印search_tuple(dtuple_print())
STEP 1: no search_tuple
STEP 2:
DATA TUPLE: 2 fields;
0: len 4; hex 80000001; asc ;;
1: len 4; hex 80000028; asc (;;
STEP 3:
DATA TUPLE: 1 fields;
0: len 4; hex 80000001; asc ;;
STEP 4:
DATA TUPLE: 2 fields;
0: len 4; hex 80000002; asc ;;
1: len 4; hex 80000028; asc (;;
STEP 5:
DATA TUPLE: 1 fields;
0: len 4; hex 80000002; asc ;;
从上述描述可以看到使用skip-scan的方式避免了全索引扫描,从而提升了性能,尤其是在索引前缀列区分度比较低的时候
条件
skip scan可以通过Hint或者optimizer_switch来控制(skip_scan),默认是打开的。根据worklog的描述,对于如下query:
SELECT A_1,...,A_k, B_1,...,B_m, C
FROM T
WHERE
EQ(A_1,...,A_k)
AND RNG(C);
需要满足如下条件才能使用skip scan:
A) Table T has at least one compound index I of the form:
I = <A_1,...,A_k, B_1,..., B_m, C ,[D_1,...,D_n]>
Key parts A and D may be empty, but B and C must be non-empty.
B) Only one table referenced.
C) Cannot have group by/select distinct
D) Query must reference fields in the index only.
E) The predicates on A_1...A_k must be equality predicates and they need
to be constants. This includes the 'IN' operator.
F) The query must be a conjunctive query.
In other words, it is a AND of ORs:
(COND1(kp1) OR COND2(kp1)) AND (COND1(kp2) OR ...) AND ...
G) There must be a range condition on C.
H) Conditions on D columns are allowed. Conditions on D must be in
conjunction with range condition on C.
ref: get_best_skip_scan()
当skip scan拥有更低的cost时,会被选择,计算cost的函数是cost_skip_scan(),由于索引统计信息中已经基于不同的前缀列值估算了distinct value的个数(rec_per_key), 可以基于此去预估可能需要读的行数。 更具体的可以参考wl#11322中的描述,笔者对此不甚了解,故不做笔墨
ref: cost_skip_scan()
参考
官方文档:Skip Scan Range Access Method
WL#11322: SUPPORT LOOSE INDEX RANGE SCANS FOR LOW CARDINALITY
Bug#88103
相关代码
本文作者:zhaiwx_yinfeng
本文为云栖社区原创内容,未经允许不得转载。
干货 | 解读MySQL 8.0新特性:Skip Scan Range的更多相关文章
- Mysql 8.0 新特性测试
Mysql 8.0 新特性测试 Role MySQL8.0版本添加了role特性,role是一种逻辑概念是权限的集合,可以将一个或以上的权限赋予给role,再将role赋给user.Oracle,Po ...
- MySQL 8.0 新特性梳理汇总
一 历史版本发布回顾 从上图可以看出,基本遵循 5+3+3 模式 5---GA发布后,5年 就停止通用常规的更新了(功能不再更新了): 3---企业版的,+3年功能不再更新了: 3 ---完全停止更新 ...
- [干货来袭]C#6.0新特性
微软昨天发布了新的VS 2015 ..随之而来的还有很多很多东西... .NET新版本 ASP.NET新版本...等等..太多..实在没消化.. 分享一下也是昨天发布的新的C#6.0的部分新特性吧.. ...
- [干货来袭]C#7.0新特性(VS2017可用)
前言 微软昨天发布了新的VS 2017 ..随之而来的还有很多很多东西... .NET新版本 ASP.NET新版本...等等..太多..实在没消化.. 分享一下其实2016年12月就已经公布了的C#7 ...
- [干货来袭]C#7.0新特性(VS2017可用)(转)
出处:http://www.cnblogs.com/GuZhenYin/p/6526041.html 微软昨天发布了新的VS 2017 ..随之而来的还有很多很多东西... .NET新版本 ASP.N ...
- MySQL 8.0新特性之原子DDL
文章来源:爱可生云数据库 简介 MySQL8.0 开始支持原⼦ DDL(atomic DDL),数据字典的更新,存储引擎操作,写⼆进制日志结合成了一个事务.在没有原⼦DDL之前,DROP TABLE ...
- Mysql 8.0 新特性
转载:https://www.jianshu.com/p/be29467c2b0c
- 【mysql】mysq8.0新特性
一.MySQL8.0简介 mysql8.0现在已经发布,2016-09-12第一个DM(development milestone)版本8.0.0发布.新的版本带来很多新功能和新特性,对性能也得到 ...
- 跨时代的MySQL8.0新特性解读
目录 MySQL发展历程 MySQL8.0新特性 秒级加列 性能提升 文档数据库 SQL增强 共用表表达式(CTEs) 不可见索引(Invisible Indexes) 降序索引(Descending ...
随机推荐
- ImportError: No module named 'pycocotools'
错误原因很简单,就是缺少了pycocotools这个包,首先你需要pip install pycocotools,看少了什么包没安装,我这里少了Cython 于是我又安装了Cython,然后再安装py ...
- 粗浅看 Tomcat系统架构分析
原文出处: 吴士龙 http://www.importnew.com/21112.html Tomcat的结构很复杂,但是Tomcat也非常的模块化,找到了Tomcat最核心的模块,就抓住了Tomca ...
- Luogu P3953 逛公园(最短路+记忆化搜索)
P3953 逛公园 题面 题目描述 策策同学特别喜欢逛公园.公园可以看成一张 \(N\) 个点 \(M\) 条边构成的有向图,且没有自环和重边.其中 \(1\) 号点是公园的入口,\(N\) 号点是公 ...
- Web应用托管服务(Web+)隐藏的十个上云最佳姿势
随着云计算浪潮的推进,技术架构云化已经成为大势所趋.特别是最近由CNCF推动的云原生概念,将符合云原生标准的各种开源技术方案推向了前所未有的高度.在这一波浪潮的推动下,越来越多的企业开始了自身的数字化 ...
- JQuery或JS判断浏览器内核版本号以及是否支持W3C盒子模型
jQuery 从 1.9 版开始,移除了 $.browser 和 $.browser.version , 取而代之的是 $.support .在更新的 2.0 版本中,将不再支持 IE 6/7/8. ...
- UOJ#422. 【集训队作业2018】小Z的礼物
#422. [集训队作业2018]小Z的礼物 min-max容斥 转化为每个集合最早被染色的期望时间 如果有x个选择可以染色,那么期望时间就是((n-1)*m+(m-1)*n))/x 但是x会变,中途 ...
- Redis → Windows下搭建redis集群
一,redis集群介绍 Redis cluster(redis集群)是在版本3.0后才支持的架构,和其他集群一样,都是为了解决单台服务器不够用的情况,也防止了主服务器宕机无备用服务器,多个节点网络互联 ...
- history-之前发生了什么
查看一下之前服务器上执行过的命令.看一下总是没错的,加上前面看的谁登录过的信息,应该有点用.另外作为admin要注意,不要利用自己的权限去侵犯别人的隐私哦. 到这里先提醒一下,等会你可能会需要更新 H ...
- Struts_改写客户列表练习
1.CustomerAction修改放入ActionContext 2.list.jsp使用struts标签库
- CF 848C
听说,一个好的oier是题目喂出来的. 题目 给定长度为n的数组, 定义数字X在[l,r]内的值为数字X在[l,r]内最后一次出现位置的下标减去第一次出现位置的下标 给定m次询问, 每次询问有三个整数 ...