什么是降序索引

大家可能对索引比较熟悉,而对降序索引比较陌生,事实上降序索引是索引的子集。

我们通常使用下面的语句来创建一个索引:

create index idx_t1_bcd on t1(b,c,d);

上面sql的意思是在t1表中,针对b,c,d三个字段创建一个联合索引。

但是大家不知道的是,上面这个sql实际上和下面的这个sql是等价的:

create index idx_t1_bcd on t1(b asc,c asc,d asc);

asc表示的是升序,使用这种语法创建出来的索引叫做升序索引。也就是我们平时在创建索引的时候,创建的都是升序索引。

可能你会想到,在创建的索引的时候,可以针对字段设置asc,那是不是也可以设置desc呢?

当然是可以的,比如下面三个语句:

create index idx_t1_bcd on t1(b desc,c desc,d desc);

create index idx_t1_bcd on t1(b asc,c desc,d desc);

create index idx_t1_bcd on t1(b asc,c asc,d desc);

这种语法在mysql中也是支持的,使用这种语法创建出来的索引就叫降序索引,关键问题是:在Mysql8.0之前仅仅只是语法层面的支持,底层并没有真正支持。

我们分别使用Mysql7、Mysql8两个版本来举例子说明一下:

在Mysql7、Mysql8中分别创建一个表,有a,b,c,d,e五个字段:

create table t1 (

a int primary key,

b int,

c int,

d int,

e varchar(20)

) engine=InnoDB;

然后分别创建一个降序索引:

create index idx_t1_bcd on t1(b desc,c desc,d desc);

创建成功后,我们使用以下sql查看一下索引信息:

show index from t1;

Mysql7中你将得到结果:

Mysql8中你将得到结果:

image.png

我们只关心Key_name为idx_t1_bcd的三行记录,细心的你应该可以发现,这两个结果中的Collation字段的结果是不一样的:在Mysql7中,Collation字段的结果为A,A,A,表示b,c,d三个字段的排序方式是asc

在Mysql8中,Collation字段的结果为D,D,D,表示b,c,d三个字段的排序方式是desc

但是我们在创建索引的时候,明明在语法层面已经指定了b,c,d三个字段的排序方式是desc,这就可以看出来在Mysql7中降序索引只是语法层面的支持,底层并没有真正支持,并且固定是升序索引。而在Mysql8中则真正从底层支持了降序索引。

到此为止,大家应该对升序索引和降序索引有了一个大概的了解,但并没有真正理解,因为大家并不知道升序索引与降序索引底层到底是如何实现的。

升序索引底层实现

我们知道,索引是用来提高查询速度的,但是为什么索引能提高查询速度呢?

给定你一个数列,比如[1,3,7,9,2,5,4,6,8],这是一个无序的数列或数组,现在如果想提高这个数列的查询速度,你首先会做什么? 我相信大部分人都能够想到先排序,先把这个无序的数列,按从小到大的顺序进行排序,比如得到[1,2,3,4,5,6,7,8,9],有了这个有序的数列之后,我们就可以利用比如二分法等等算法来提高这个数列的查询速度了。

我举这个例子想告诉大家的是:想提高数据集合的查询速度,首先你可以对这些数据进行排序。

所以,对Mysql表中的存储的数据也是一样的,我们如果想提高这个表的查询速度,我们可以先对这个表里的数据进行排序,那么表里的某一行数据包括了很多字段,我们现在想对这些数据行进行排序,我们应该根据哪些字段来确定这个顺序呢?这就是索引,在创建索引的时候你所指定的列就是用来对表里的数据行进行排序的。

比如我们仍然利用上面所创建的t1表,向t1表里插入8条数据:

insert into t1 values(4,3,1,1,'d');

insert into t1 values(1,1,1,1,'a');

insert into t1 values(8,8,8,8,'h');

insert into t1 values(2,2,2,2,'b');

insert into t1 values(5,2,3,5,'e');

insert into t1 values(3,3,2,2,'c');

insert into t1 values(7,4,5,5,'g');

insert into t1 values(6,6,4,4,'f');

那么这些数据肯定是存储在文件中的,所以文件中保存这些数据的格式大概如下,顺序与插入顺序保持一致:

4311d

1111a

8888h

2222b

5235e

3322c

7455g

6644f注意,t1是Innodb的存储引擎,而且a字段是主键,所以Innodb存储引擎在处理这些插入的数据时,会按主键进行排序,也就是上面我说的文件中保存这些数据的格式是不准确的,因为不想篇幅太长,所以不去深究,感兴趣的同学可以关注一波公众号:1点25,我会专门写一篇文章来讲解Innodb中索引的具体实现,包括B+树到底是如何生成的。

而如果我们基于上面的这种存储方式,来查找数据,比如查找a=3的这行记录,查找需要从第一行记录开始查找,那么要查找6次,而如果我们将上面的数据按照a字段的大小来进行排序:

1111a

2222b

3322c

4311d

5235e

6644f

7455g

8888h

排好序之后,如果我们还是查找a=3的这行记录,我们只需要查3次了。而且这样还有一个好处就是,如果我们现在需要查找a=3.5这行数据,如果我们基于未排序之前的存储方式,我们需要查询所有8行数据最终确定a=3.5这行数据不存在,而如果我们利用排好序之后的存储方式,我们就只需要查4次就好了,因为当你查到4311d这行记录时,你会发现4>3.5了,已经可以确定a=3.5的这行记录不存在了。

而如果我们现在对t1创建一个索引,就像上面创建索引一样,如果我们写的是下面的sql:

create index idx_t1_bcd on t1(b,c,d);

这个sql表示要对t1创建一个索引,索引字段是b,c,d,并且是升序的,所以实际上就是对原本的数据按照b,c,d三个字段进行排序,那么排序之后类似:

1111a

2222b

5235e

4311d

3322c

7455g

6644f

8888h

可以好好看下,上面的记录是按照b,c,d三个字段来对数据行就行排序的,比如1111a中的b,c,d三个字段的值是111,而2222b中的b,c,d三个字段的值是222, 111是小于222的,所以对应的行排在前面。

那么数据如果这样排序有什么好处呢?其实和刚刚按a字段排序之后的好处是类似的,比如你现在想来查找b=4 and c=4 and d=4的数据也是能查询更快的,实际上这就是索引的原理: 我们对某个表创建一个索引,就是对这个表中的数据进行排序,而排好序之后的数据是能够提高查询速度。还有一点需要注意的是,排序有很多中方式,或者所可以利用一些数据结构,比如二叉树、红黑树、B+树,这些数据结构实际上就是对数据进行排序,只是排序的形式各不相同而已,每种数据结构有它各自的特点,而大家应该都知道,Mysql中用得最多的就是B+树了。

相信,看到这里,大家应该对索引重新有了认识,只不过我们上面举的几个例子都是升序排序,而且排好序之后的数据不仅可以提高查询速度,而且对于order by也是管用的,比如我们如果现在想对t1进行order by b asc,c asc,d asc;对于这个排序,如果已经在t1表建立了b,c,d的升序索引,那么就代表对t1表中的数据已经提前按照b,c,d排好序了,所以对于order by语句可以直接使用已经排好序的数据了,不用利用filesort再次进行排序了。

而且如果我们的order by是order by b desc, c desc, d desc,同样可以利用b,c,d的升序索引,因为如果是order by b asc,c asc,d asc就从上往下遍历即可,如果是order by b desc, c desc, d desc就从下往上遍历即可。

那么,如果是order by b asc, c desc, d desc呢?这个order by是不是就没有办法利用b,c,d的升序索引了。

这个时候就需要降序索引了。

降序索引底层实现

我们花了较大篇幅介绍了升序索引的实现原理,总结来说就是对表中的数据按照指定的字段比较大小进行升序排序。

升序是什么?是数据进行大小比较后,是小的在上,大的在下,或者如果是B+树的话就是小的在左,大的在右。而降序就是大的在上,小的在下,或者如果是B+树的话就是大的在左,小的在右。

所以,对于上面的那份原始数据:

4311d

1111a

8888h

2222b

5235e

3322c

7455g

6644f

复制代码

如果我们将这份数据按照a desc进行排序就是:

8888h

7455g

6644f

5235e

4311d

3322c

2222b

1111a

非常简单吧,那如果我们将这份数据按照b desc, c desc, d desc排序就是:

8888h

6644f

7455g

3322c

4311d

5235e

2222b

1111a

也非常简单,那如果我们要将这份数据按照b desc, c asc, d desc排序呢?这是不是就有点懵了?

其实不难,排序其实就是对数据比较大小,我们用下面三行数据来模拟一下:

3322c

7455g

4311d

首先,按照b desc, c desc, d desc来排序,得到结果如下:

7455g

3322c

4311d

按照b desc, c asc, d desc来排序,得到结果如下:

7455g

4311d

3322c

可能一部分大佬已经能理解,实际上b desc所表达的意思就是b字段数据大者在上,数据小者在下,数据相等的话则开始比较c字段,而c字段是按升序排的,也就是c字段数据小者在下,数据大者在上。所以就得到了上面的结果。

这就是降序索引。

总结

实际上升序索引和降序索引是不同的排序方式而已,Mysql8中正在实现了降序索引后,我们在创建索引时更加灵活,可以根据业务需要的排序规则来创建合适的索引,这样能使你的查询更快。

当然本文只讲了原理,大家一定要知道Mysql中排序利用的B+树,而不是上面我举例的那种很简单的方式,但是就算用B+树原理也是一样的,比较数据的大小而已。

还有一点,现在只有Innodb存储引擎支持降序索引。

mysql创建唯一性降序索引_MySQL 8 新特性之降序索引底层实现相关推荐

  1. mysql 降序_MySQL 8 新特性之降序索引底层实现

    什么是降序索引 大家可能对索引比较熟悉,而对降序索引比较陌生,事实上降序索引是索引的子集. 我们通常使用下面的语句来创建一个索引: create index idx_t1_bcd on t1(b,c, ...

  2. SQL Server 2016新特性:列存储索引新特性

    SQL Server 2016新特性:列存储索引新特性 行存储表可以有一个可更新的列存储索引,之前非聚集的列存储索引是只读的. 非聚集的列存储索引支持筛选条件. 在内存优化表中可以有一个列存储索引,可 ...

  3. oracle12c 新增维护时间窗口,ORACLE 12C新特性-自动维护全局索引 | 信春哥,系统稳,闭眼上线不回滚!...

    今天在网上看了一篇关于12C新特性-自动维护全局索引的帖子,经测试,貌似根本不是那么回事呀.如果对分区表进行分区DDL操作,如果不加update index字句,全局索引就会失效,下面先看一下是11. ...

  4. 如何保障MySQL主从复制关系的稳定性?关键词(新特性、crash-safe)

    一 前言 MySQL 主从架构已经被广泛应用,保障主从复制关系的稳定性是大家一直关注的焦点.MySQL 5.6 针对主从复制稳定性提供了新特性: slave 支持 crash-safe.该功能可以解决 ...

  5. mysql如何批量删除索引_mysql执行大批量删除、查询和索引等操作教程

    mysql执行大批量删除 执行大批量删除的时候注意要使用上limit 因为如果不用limit,删除大量数据很有可能造成死锁 如果delete的where语句不在索引上,可以先找主键,然后根据主键删除数 ...

  6. mysql创建表时添加范式_MySql三大范式与数据库设计和表创建常用语句

    [数据库设计的三大范式] 1.第一范式(1NF First Normal Fromate):数据表中的每一列(字段),必须是不可拆分的最小单元.也就是确保每一列的原子性. 例如: userInfo: ...

  7. mysql数值比中文检索快_MySQL 千万 级数据量根据(索引)优化 查询 速度

    一.索引的作用 索引通俗来讲就相当于书的目录,当我们根据条件查询的时候,没有索引,便需要全表扫描,数据量少还可以,一旦数据量超过百万甚至千万,一条查询sql执行往往需要几十秒甚至更多,5秒以上就已经让 ...

  8. c语言 字符串 正序再倒序_新特性解读 | MySQL 8.0 索引特性3 -倒序索引

    原创作者:杨涛涛 我们今天来介绍下 MySQL 8.0 引入的新特性:倒序索引. MySQL长期以来对索引的建立只允许正向asc存储,就算建立了desc,也是忽略掉. 比如对于以下的查询,无法发挥索引 ...

  9. mysql创建表有则删除_MySQL创建表和删除表

    创建表 简单的方式 CREATE TABLE person ( number INT(11), name VARCHAR(255), birthday DATE ); 或者是 CREATE TABLE ...

最新文章

  1. 分布式缓存灵魂十连,你能坚持几个?
  2. Silverlight 3 Tools 中文版地址
  3. 前端那些事之原生js实现jquery常用方法
  4. 但凡网络工程师会这个技能,也不至于天天抱怨工资低
  5. SQL的OPENROWSET开启和使用方法
  6. boost::phoenix模块使用 istreambuf_iterator 测试 lambda 函数对象
  7. IDEA新特性:提前知道代码怎么走!
  8. selenium元素定位之 动态id, class元素定位
  9. 顺风车订单已结束仍在录音 嘀嗒出行回应录音机制
  10. wamp配置中的大小写
  11. 又涨啦!2021年6月程序员工资出炉
  12. python 爬虫 中乱码问题0xb5 和b'\x1f\x8b\x08
  13. python arp断网攻击_arp断网攻击,手把手教你arp断网攻击怎么解决
  14. 微服务系列之单体架构
  15. 汉字转拼音pinyin
  16. Linux 中 Permission denied
  17. 孙溟㠭(展)为秘鲁总统夫人‘埃莲娜卡尔普托莱多’女士治名章篆刻印章
  18. 联通数科一面+二面+面谈 经验分享 base济南
  19. 大话nbu四(nbu备份恢复catalog)
  20. 蓝桥杯算法很美笔记—排序实现题

热门文章

  1. 亚信AX58200 EtherCAT转Modbus TCP网关解决方案介绍视频
  2. 数据库的星型模型与雪花模型
  3. python文本统计单词_Python实现文本单词统计
  4. C++ 的Vector类的简单实现
  5. Spring中的bean是什么?
  6. 前任是什么东西,双十二有XMind就够了
  7. ubuntu删除文件(夹)命令
  8. 上海交大计算机考研复试刷人,2019上海交大初试第4也被刷,复试真要早准备!...
  9. 轴承座的工艺及钻孔夹具装置设计(论文+CAD图纸+答辩PPT+任务书+工序卡片+工艺规程+外文翻译……)
  10. 开发人员Review代码文档规范