MySQL 8 新特性之降序索引底层实现

什么是降序索引

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

咱们一般使用下面的语句来建立一个索引:算法

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

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

可是你们不知道的是,上面这个sql实际上和下面的这个sql是等价的:数组

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

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

可能你会想到,在建立的索引的时候,能够针对字段设置asc,那是否是也能够设置desc呢?blog

固然是能够的,好比下面三个语句:排序

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以前仅仅只是语法层面的支持,底层并无真正支持。索引

咱们分别使用Mysql七、Mysql8两个版原本举例子说明一下:io

在Mysql七、Mysql8中分别建立一个表,有a,b,c,d,e五个字段:table

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中你将获得结果:

咱们只关心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

而若是咱们基于上面的这种存储方式,来查找数据,好比查找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的数据也是能查询更快的,实际上这就是索引的原理: 咱们对某个表建立一个索引,就是对这个表中的数据进行排序,而排好序以后的数据是可以提升查询速度。

相信,看到这里,你们应该对索引从新有了认识,只不过咱们上面举的几个例子都是升序排序,并且排好序以后的数据不只能够提升查询速度,并且对于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存储引擎支持降序索引。

相关文章
相关标签/搜索