译者注:
MySQL 8.0之前,不管是否指定索引建的排序方式,都会忽略创建索引时候指定的排序方式(语法上不会报错),最终都会创建为ASC方式的索引,
在执行查询的时候,只存在forwarded(正向)方式对索引进行扫描。
关于正向索引和反向索引,逻辑上很容易理解,这里有两个相关的概念:
正向索引或者反向(倒序)索引,两者都是在构建B树索引时候的相关字段排序方式,是B索引树的逻辑存储方式
正向扫描(forward)和反向扫描( Backward index scan;)是执行查询的过程中对B树索引的扫描方式,是数据执行计划时候的一种索引扫描方式
关于正向扫描或者反向扫描不是随意的,受sql语句中(正/反向)排序方式以及(正/反向)索引的影响
之前在sqlserver中简单写过一点类似的东西,https://www.cnblogs.com/wy123/p/5552719.html

整体上看,抛开正向索引和倒序索引,在扫描扫描的过程中,正向索引扫描的在性能上,稍微优于反向索引扫描。
不过,即便是反向索引扫描,也是优化器根据具体查询进行优化的结果,并非一个不好的选择。


原文链接:http://mysqlserverteam.com/mysql-8-0-labs-descending-indexes-in-mysql/

以下为译文:

从8.0优化器实验室发布开始,MySQL开始支持倒序索引。
正如我将在本文中详细介绍的,这个新特性可以用来消除对结果排序的需求,并在许多查询中带来性能改进。

简介

在此版本之前,所有索引都是按升序创建的。当语法本身被解析时,元数据不会被保留。例如在MySQL 5.7中:

mysql 5.7> CREATE TABLE t1 (a INT, b INT, INDEX a_desc_b_asc (a DESC, b ASC));
Query OK, 0 rows affected (0.47 sec) mysql 5.7> SHOW CREATE TABLE t1\G
*************************** 1. row ***************************
Table: t1
Create Table: CREATE TABLE `t1` (
`a` int(11) DEFAULT NULL,
`b` int(11) DEFAULT NULL,
KEY `a_desc_b_asc` (`a`,`b`) <-- 创建索引时候的元数据没有被保留
) ENGINE=InnoDB DEFAULT CHARSET=latin1
1 row in set (0.00 sec)

应该注意的是,MySQL 5.7 optimizer能够反向扫描一个升序索引(按照降序排列),其成本较高

(译者注:以上是原文中写道的,MySQL 5.7中不知道怎么去判断在对索引扫描的时候,究竟是正向扫描还是反向扫描)。
如下可以进一步测试,我们可以看到正向索引扫描比反向索引扫描好~15%。
不能支持倒叙索引的主要限制是,优化器必须对混合顺序(如DESC、b ASC的顺序)使用文件排序。

MySQL 8.0中的改进

引入反向索引后,InnoDB现在可以按照降序顺序存储数据行,优化器将在查询中请求降序时利用它。
重复上面的例子,我们可以看到在创建表时索引顺序信息被正确地保留了:

mysql 8.0> CREATE TABLE t1 (a INT, b INT, INDEX a_desc_b_asc (a DESC, b ASC));
Query OK, 0 rows affected (0.47 sec) mysql 8.0> show create table t1;
+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------+
| t1 | CREATE TABLE `t1` (
`a` int(11) DEFAULT NULL,
`b` int(11) DEFAULT NULL,
KEY `a_desc_b_asc` (`a` DESC,`b`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

为了区分向后和向前索引扫描,还改进了EXPLAIN的输出。
对于MySQL-5.7,除了查询2和查询6之外,我们对所有查询都使用反向索引扫描或文件排序,因为这两个查询只需要升序。

Query 1: SELECT * FROM t1 ORDER BY a DESC;

mysql 8.0> explain SELECT * FROM t1 ORDER BY a DESC;
+----+-------------+-------+------------+-------+---------------+--------------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+-------+---------------+--------------+---------+------+------+----------+-------------+
| 1 | SIMPLE    | t1   | NULL    | index | NULL | a_desc_b_asc | 10 | NULL | 10 | 100.00 | Using index |
+----+-------------+-------+------------+-------+---------------+--------------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

Query 2: SELECT * FROM t1 ORDER BY a ASC;

mysql 8.0> explain SELECT * FROM t1 ORDER BY a ASC;
+----+-------------+-------+------------+-------+---------------+--------------+---------+------+------+----------+----------------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+-------+---------------+--------------+---------+------+------+----------+----------------------------------+
| 1 | SIMPLE | t1 | NULL | index | NULL | a_desc_b_asc | 10 | NULL | 10 | 100.00 | Backward index scan; Using index |
+----+-------------+-------+------------+-------+---------------+--------------+---------+------+------+----------+----------------------------------+
1 row in set, 1 warning (0.00 sec)

Query 3: SELECT * FROM t1 ORDER BY a DESC, b ASC;

mysql 8.0> EXPLAIN SELECT * FROM t1 ORDER BY a DESC, b ASC;
+----+-------------+-------+------------+-------+---------------+--------------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+-------+---------------+--------------+---------+------+------+----------+-------------+
| 1 | SIMPLE | t1 | NULL | index | NULL | a_desc_b_asc | 10 | NULL | 10 | 100.00 | Using index |
+----+-------------+-------+------------+-------+---------------+--------------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

Query 4: SELECT * FROM t1 ORDER BY a ASC, b DESC;

mysql 8.0> EXPLAIN SELECT * FROM t1 ORDER BY a ASC, b DESC;
+----+-------------+-------+------------+-------+---------------+--------------+---------+------+------+----------+----------------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+-------+---------------+--------------+---------+------+------+----------+----------------------------------+
| 1 | SIMPLE | t1 | NULL | index | NULL | a_desc_b_asc | 10 | NULL | 10 | 100.00 | Backward index scan; Using index |
+----+-------------+-------+------------+-------+---------------+--------------+---------+------+------+----------+----------------------------------+
1 row in set, 1 warning (0.00 sec)

Query 5: SELECT * FROM t1 ORDER BY a DESC, b DESC;

mysql 8.0> EXPLAIN SELECT * FROM t1 ORDER BY a DESC, b DESC;
+----+-------------+-------+------------+-------+---------------+--------------+---------+------+------+----------+-----------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+-------+---------------+--------------+---------+------+------+----------+-----------------------------+
| 1 | SIMPLE | t1 | NULL | index | NULL | a_desc_b_asc | 10 | NULL | 10 | 100.00 | Using index; Using filesort |
+----+-------------+-------+------------+-------+---------------+--------------+---------+------+------+----------+-----------------------------+
1 row in set, 1 warning (0.01 sec)

Query 5: SELECT * FROM t1 ORDER BY a ASC, b ASC;

mysql 8.0> EXPLAIN SELECT * FROM t1 ORDER BY a ASC, b ASC;
+----+-------------+-------+------------+-------+---------------+--------------+---------+------+------+----------+-----------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+-------+---------------+--------------+---------+------+------+----------+-----------------------------+
| 1 | SIMPLE | t1 | NULL | index | NULL | a_desc_b_asc | 10 | NULL | 10 | 100.00 | Using index; Using filesort |
+----+-------------+-------+------------+-------+---------------+--------------+---------+------+------+----------+-----------------------------+
1 row in set, 1 warning (0.00 sec)

当表中有一个索引a_desc_b_asc (a DESC, b ASC)时,以下是上述6个查询的性能指标。

数据大小为1000万行。在MySQL-5.7中,它是a_asc_b_asc(a ASC, b ASC),因为不支持倒叙索引。

性能指标的解释:

1, 对于查询1,也即ORDER BY a DESC;:
我们看到查询1中性能的提升,因为请求的语句排序是“a”列的DESC
译者注:因为MySQL8.0中可以建立倒叙索引,查询1按照a字段desc排序,直接走正向(forwarded)索引扫描即可完成查询,
避免了在MySQL5.7中查询出来数据之后再进行排序操作的步骤

2,对于查询2:
由于查询2的排序为正序(译者注:与索引的顺序相反,因此需要反向扫描),由于反向索引扫描,
在MySQL-8.0中(相对于查询1)执行向反向索引扫描需要更多的时间
(注意,从图中可以看出,MySQL-8.0总体上表现更好。MySQL 5.7中正向索引扫描,与MySQL 8.0中反向索引扫描花费的时间(几乎)相同)

3,对于查询3 也即ORDER BY a DESC, b ASC;:
查询3的排序方式与查询1类似,然而在MySQL-5.7中,对于任何请求混合顺序的查询,会对查询结果重新排序,因此性能差别是巨大的。

4,对于查询4 也即 ORDER BY a ASC, b DESC;
可以看到,在MySQL 8.0中,查询4执行的是反向索引扫描,因此比查询3花费了更多的时间,
尽管如此,在查询5和查询6中,排序的方式是(a DESC, b DESC)/(a ASC, b ASC),不管是正向扫描还是反向扫描,都无法满足排序需求,因此会用到filesort
但是,在这种情况下,由于在MySQL-5.7中ASC/DESC索引标志被忽略(译者注:MySQL 5.7中没有正向和反向索引的概念),因此MySQL-5.7可以使用(正向/反向)索引扫描来给出请求的顺序。

5,如果用户想要避免查询5和查询6的filesorts,可以修改表以添加一个键(a ASC, b ASC)。
此外,如果用户也想避免反向索引扫描,可以同时添加(a ASC, b DESC)和(a DESC, b DESC)。

下面是添加了第5点下的额外索引后的MySQL-5.7.14和MySQL-8.0-labs的最后对比:

注意,在MySQL-5.7中,我们不能添加额外的索引来提高上述查询的性能。
而且,有了这个特性,在某些情况下可以避免物化,比如在连接中的第一个表上请求混合顺序。
在一些用例中,反向索引提高了性能。区间扫描访问方法也使用反向索引。
虽然并不是所有的范围扫描访问方法都使用反向索引,但我们将在未来尝试消除这些限制。

改进

随着倒序索引(反向索引)的引入,我们已经删除了对隐式排序的支持,结果是作为GROUP BY的一部分提到的列的升序。
除了上述改进外,我们还看到在一些情况下性能得到了改善,这些情况下的顺序是隐含的,但可能不是必需的。

总结

我们很高兴能够解决MySQL社区长期存在的功能请求之一。请了解倒叙索引的特性,让我们知道你的想法!

 

(译)MySQL 8.0实验室---MySQL中的倒序索引(Descending Indexes)的更多相关文章

  1. mysql jdbc8.0连接mysql

  2. MySQL 8.0有什么新功能

    https://mysqlserverteam.com/whats-new-in-mysql-8-0-generally-available/ 我们自豪地宣布MySQL 8.0的一般可用性. 现在下载 ...

  3. mysql 8.0 初识

    1 下载并安装mysql 8.0官网下载比较慢,这里选择163的镜像http://mirrors.163.com/mysql/Downloads/MySQL-8.0/下载版本mysql-8.0.14- ...

  4. MySQL 8.0部分弃用的参数整理

    最近整理了一下MySQL 8.0的自动化安装,其中用到了一个MySQL 5.7版本的自定义配置文件,由于没有对(MySQL 8.0)做针对性修改,导致安装过程中出现了一些错误其中部分原因就是MySQL ...

  5. MySQL 8.0 技术详解

    MySQL 8.0 简介 MySQL 5.7 到 8.0,Oracle 官方跳跃了 Major Version 版本号,随之而来的就是在 MySQL 8.0 上做了许多重大更新,在往企业级数据库的路上 ...

  6. mysql系列十一、mysql优化笔记:表设计、sql优化、配置优化

    可以从这些方面进行优化: 数据库(表)设计合理 SQL语句优化 数据库配置优化 系统层.硬件层优化 数据库设计 关系数据库三范式 1NF:字段不可分; 2NF:有主键,非主键字段依赖主键; 3NF:非 ...

  7. SET FOREIGN_KEY_CHECKS=0;在Mysql中取消外键约束。

    SET FOREIGN_KEY_CHECKS=0;在Mysql中取消外键约束.

  8. MySQL 8.0 中统计信息直方图的尝试

    直方图是表上某个字段在按照一定百分比和规律采样后的数据分布的一种描述,最重要的作用之一就是根据查询条件,预估符合条件的数据量,为sql执行计划的生成提供重要的依据在MySQL 8.0之前的版本中,My ...

  9. MySQL 并行复制演进及 MySQL 8.0 中基于 WriteSet 的优化

    MySQL 8.0 可以说是MySQL发展历史上里程碑式的一个版本,包括了多个重大更新,目前 Generally Available 版本已经已经发布,正式版本即将发布,在此将介绍8.0版本中引入的一 ...

随机推荐

  1. python 基础之注释变量常量

    一:注释 注释: 就是对代码的解释 方便大家阅读代码 1.注释的分类 (1)单行注释 #  在python中在行首添加一个#号就将这一行进行注释 #单行注释: 用#开头,后面跟上任意字符串 #pyth ...

  2. Element UI toggleRowExpansion用法

    背景: 官方说明文档没有具体代码示例 一.官方文档 方法名: toggleRowExpansion 说明: 用于可展开表格,切换某一行的展开状态,如果使用了第二个参数,则是设置这一行展开与否(expa ...

  3. python io-os

    #IO - os import os; #文件改名 #os.rename('io.txt','newio.txt'); #删除文件 #os.remove('io2.txt'); #创建文件夹(目录) ...

  4. 什么是HDR?

    参考:https://baijiahao.baidu.com/s?id=1606763887374415267&wfr=spider&for=pc HDR——即高动态范围图像(High ...

  5. M25P16中文版

    转载:https://blog.csdn.net/weiweiliulu/article/details/23666717 1.M25P16概述     M25P16是一款带有先进写保护机制和高速SP ...

  6. 你云我云•兄弟夜谈会 第三季 企业IT架构

    你云我云•兄弟夜谈会 第三季 企业IT架构 你云我云•兄弟夜谈会 第二季 5G 你云我云•兄弟夜谈会 第一季 企业云 0. 概况 时间:2019年2月23日 22:00~23:30 主题:企业IT架构 ...

  7. Selenium之动作链(ActionChains)

    用selenium做自动化,有时候会遇到需要模拟鼠标操作才能进行的情况,比如单击.双击.点击鼠标右键.拖拽等等.而selenium给我们提供了一个类来处理这类事件——ActionChains   se ...

  8. Butterknife--Android Butterknife使用方法总结(转)

    原文链接:http://blog.csdn.net/donkor_/article/details/77879630 前言: ButterKnife是一个专注于Android系统的View注入框架,以 ...

  9. Qt文件系统之QFile

    QFile文件操作 文件打开方式: QIODevice::NotOpen    0x0000   设备不打开.QIODevice::ReadOnly    0x0001   设备 以只读的方式打开.Q ...

  10. ABAP其实也是挺好的语言

    目前工作当中使用的编程语言是SAP平台的ABPA语言,出于好奇心,我想把之前用JAVA(用C++也写过,事实上,我每学一个新的语言,就会尝试去实现这个小程序)写过的计算一个正整数的因子的程序用ABAP ...