MySQL8.0 - 新特性 - Descending Index
前言
在MySQL8.0之前的版本中,innodb btree索引中的记录都是严格按照的key的顺序来存储的,但有些时候当我们需要倒序扫描时,效率就会很低。为了解决这个问题,从MySQL8.0版本开始支持在索引Key中倒序存储。你可以按照实际的sql负载来决定如何创建索引,例如你的查询中有Order by a desc, b asc,就可以创建索引key(a desc, b asc),而在8.0之前的版本中则可能需要代价比较大的filesort来进行, 此外逆序扫描Btree也有额外的开销,例如扫描时的page切换,page内扫描,都比正序扫描的开销要大。
本文简单介绍下用法,并分析下对应的代码实现
以下基于当前最新MySQL8.0.13版本
使用
其实对应的语法一直是存在的,只是没有做具体的实现,直到8.0版本才真正实现,使用也很简单,在创建索引时,对索引列加asc/desc关键字,举个简单的例子:
mysql> CREATE TABLE t1 (a INT PRIMARY KEY, b INT, KEY a_idx(a DESC, b ASC));
Query OK, 0 rows affected (0.05 sec)mysql> INSERT INTO t1 VALUES(1,1),(2,2),(3,3);
Query OK, 3 rows affected (0.02 sec)
Records: 3 Duplicates: 0 Warnings: 0mysql> SELECT b FROM t1 FORCE INDEX(a_idx);
+------+
| b |
+------+
| 3 |
| 2 |
| 1 |
+------+
3 rows in set (0.00 sec)mysql> SELECT b FROM t1 FORCE INDEX(PRIMARY);
+------+
| b |
+------+
| 1 |
| 2 |
| 3 |
+------+
3 rows in set (0.00 sec)
如上例,可以看到指定不同的索引给出的结果顺序也是不一样的。
mysql> EXPLAIN SELECT * FROM t1 ORDER BY a DESC, b;
+----+-------------+-------+------------+-------+---------------+-------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+-------+---------------+-------+---------+------+------+----------+-------------+
| 1 | SIMPLE | t1 | NULL | index | NULL | a_idx | 9 | NULL | 3 | 100.00 | Using index |
+----+-------------+-------+------------+-------+---------------+-------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)
上例中可以看到explain的结果中没有filesort, 而在之前的版本中对于这样的sql是需要进行排序的。
优化器在选择索引时也会考虑到索引列的顺序,目前还有些条件限制:
- 由于涉及到数据的存储,目前只支持InnoDB
- Descending index 无法使用change buffer
- Descneding index不支持fulltext或spatial index, 选择desc关键字会报错
- GROUP BY不在隐式的保证顺序性,只有明确的指定asc/desc,才去确保顺序
实现
笔者主要工作是在innodb引擎,对server层不甚了解,本文也主要关注innodb的改动。实际上这个特性的改动主要在server层的优化器和执行器,对于innodb来说,尽管数据存储发生了变化,但改动反而很少。
数据词典:
索引上的列属性被持久化到数据词典表(dd::Index)
dd::fill_dd_indexes_from_keyinfodd::fill_dd_index_elements_from_key_parts
key_rec_cmp
:
比较的两个key不是大小关系,而是在索引上的前后关系,因此需要考虑键值列上是asc还是desc的
对于range查询,在之前的版本中总是min_Key被传到innodb作为search_tuple来定位btree,但如果是descending index,则需要选择max_key来作为search tuple (ref: SEL_ARG::get_min_flag(), SEL_ARG::get_max_flag(), SEL_ROOT::store_min_key)
InnoDB record compare:
为了支持这个特性,innodb的改动实际上并不大,大部分代码都是没有变化的,这主要是因为InnoDB使用了统一的比较函数来决定key值位置,索引对象传递到底层的比较函数中,以获取是否存在descending column.
相关函数:
cmp_dtuple_rec_with_match_low
cmp_whole_field
cmp_data
判断是否是descending index:
dict_index_has_desc(): 这个函数会扫描索引上所有的列,确保没有desc column, 这个函数看起来有点效率问题,我们可以给dict_index_t加个flag来判断,无需每次遍历
参考文档:
1.官方文档
2. wl#1074: Add Descending indexes support
3.MySQL 8.0 Labs – Descending Indexes in MySQL
4.MySQL 8.0: Descending Indexes Can Speed Up Your Queries
5.相关代码
MySQL8.0 - 新特性 - Descending Index相关推荐
- MySQL基础篇13【MySQL8.0新特性】
目录 1. MySQL8新特性概述 1.1 MySQL8.0 新增特性 1.2 MySQL8.0移除的旧特性 新特性1:窗口函数 2.1 使用窗口函数前后对比 2.2 窗口函数分类 2.3 语法结构 ...
- Mysql8.0新特性之详细版本
1. 账户与安全 用户创建与授权 之前:创建用户并授权 1 grant all privileges on *.* to 'myuser'@'%' identified by '3edc #EDC'; ...
- mysql8.0 新特性
1. 账户与安全# 用户创建与授权 之前:创建用户并授权 1 grant all privileges on *.* to 'myuser'@'%' identified by '3edc#EDC' ...
- MySQL8.0 - 新特性 - 临时表改进
temptable engine 我们知道UNION, DERIVED TABLE, CTE, 子查询或者distinct order by之类的查询都可能用到临时表来存储中间结果,官方文档中列举了几 ...
- 深入解读MySQL8.0 新特性 :Crash Safe DDL
前言 在MySQL8.0之前的版本中,由于架构的原因,mysql在server层使用统一的frm文件来存储表元数据信息,这个信息能够被不同的存储引擎识别.而实际上innodb本身也存储有元数据信息.这 ...
- 深入解读MySQL8.0 新特性 :Crash Safe DDL 1
前言 在MySQL8.0之前的版本中,由于架构的原因,mysql在server层使用统一的frm文件来存储表元数据信息,这个信息能够被不同的存储引擎识别.而实际上innodb本身也存储有元数据信息.这 ...
- MySQL8.0 - 新特性 - Instant Add Column
MySQL8.0开始对一些DDL操作做了大量的优化,例如原子DDL, 快速DDL(只修改元数据),前者解决了长期以来mysql的一大诟病,后者则提升了dba同学的生活品质 官方文档列出了一些可以快速d ...
- MySQL8.0 - 新特性 - 安全及权限相关改进
MySQL8.0里引入了不少关于权限的改动,从这些改动可以看出来,权限管理更加的规范和遍历了,这和我们之前为rds mysql增加了大量权限管理很类似,想来Oracle也是通过这些改动为其云业务服务的 ...
- Mysql基础篇(10)—— MySQL8.0新特性概览
新增的新特性 更简便的NoSQL支持. 更好的索引,新增了隐藏索引和降序索引.隐藏索引可以用来去掉索引对查询性能的影响.在查询中混合存在多列索引时,使用降序索引可以提高查询的性能. 更完善的JSON支 ...
- MySQL8.0新特性——默认使用caching_sha2_password作为身份验证插件
mysql5.8开始将caching_sha2_password作为默认的身份验证插件 该caching_sha2_password和 sha256_password认证插件提供比mysql_nati ...
最新文章
- 自定义滚动条Js简版
- linux下,MySQL默认的数据文档存储目录为/var/lib/mysql。
- JavaScript --- 表单focus,blur,change事件的实现
- 用于大型的科学计算的计算机,科学计算器广泛适用于大、中、小学生、教师、科研人员及其他各界...
- 【bfs】极其简单的最短路问题
- Android官方开发文档Training系列课程中文版:数据存储之文件存储
- Android:四大架构的优缺点,你真的了解吗? 1
- php mysqli分页,PHP使用Mysqli类库实现完美分页效果的方法_PHP
- 【C语言】流程图符号及流程图
- CVPR 2019 论文汇总(按方向划分,0506 更新中)
- 【可达性分析中的增量更新和原始快照】
- java并发原理实战(8)-- lock接口使用和认识
- 电子信箱怎么样注册?邮箱格式怎么写?
- 数字音频总线A2B开发详解二(A2B-主和从的配置和编程详解)
- 操作系统 --- 虚拟文件系统
- 小议SEO做网站关键字优化
- c# imager让图片有圆角unity_使用Unity着色器实现精灵(Sprite)涂鸦效果
- JS弹出模态窗口下拉列表特效
- vue纵向 轮播_vue滑动轮播图插件vueswiper
- 图片上传(简单例子)
热门文章
- 用Python3在牛客网acm模式刷题怎么输入输出
- 【电驴傻瓜教程-我为人人,人人为我】
- servlet常见错误
- 流利阅读12.23 The 'great dying': rapid warming caused largest extinction event ever, report says
- 5G NR的新特征—超低时延
- 历年考研计算机专业国家线,历年工学考研国家线一览_考研国家线公布时间
- 华纳云:香港服务器哪家比较好?
- 分布式系统设计模式 - 预写日志(Write Ahead Log)
- Vue-basic 19.单文件组件
- java 线程池超时_Java定时线程池停止超时任务