什么是降序索引?您可能熟悉索引,但不熟悉降序索引。事实上,降序索引是索引的一个子集。我们通常使用如下语句来创建索引:createindexidx_t1_bcdont1(b,c,d);上述sql的意思是为t1表中的b,c,d三个字段建立联合索引。但是大家不知道的是,上面的sql其实等价于下面的sql:createindexidx_t1_bcdont1(basc,casc,dasc);asc表示升序,使用这种语法创建的索引称为升序索引。也就是我们平时创建索引的时候,创建的是升序索引。你可能会想,在创建索引的时候,可以给字段设置asc,难道也可以设置desc吗?当然也可以,比如下面三个语句:createindexidx_t1_bcdont1(bdesc,cdesc,ddesc);createindexidx_t1_bcdont1(basc,cdesc,ddesc);createindexidx_t1_bcdont1(b升序,c升序,d降序);mysql也支持这种语法,使用这种语法创建的索引称为降序索引。关键问题是:Mysql8.0之前,只是语法层面的支持,底层并没有真正支持。下面用Mysql7和Mysql8两个版本来说明:分别在Mysql7和Mysql8中创建一个表,有五个字段a,b,c,d,e:createtablet1(aintprimarykey,bint,cint,dint,evarchar(20))engine=创新数据库;然后创建降序索引:createindexidx_t1_bcdont1(bdesc,cdesc,ddesc);创建成功后,我们使用如下sql查看索引信息:showindexfromt1;在Mysql7中你会得到结果:在Mysql8中你会得到结果:image.png我们只关心Key_name为idx_t1_bcd的三行记录。如果细心的话,应该可以发现这两个结果中Collat??ion字段的结果是不一样的:在Mysql7中,Collat??ion字段的结果是A,A,A,表示三个字段的排序方式b,c,d的排序方式是asc在Mysql8中,Collat??ion字段的结果是D,D,D,说明b,c,d三个字段的排序方式是desc但是我们在创建一个的时候index,可以看出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条数据:insertintot1values(4,3,1,1,'d');insertintot1values(1,1,1,1,'a');insertintot1values(8,8,8,8,'h');insertintot1values(2,2,2,2,'b');insertintot1values(5,2,3,5,'e');insertintot1values(3,3,2,2,'c');insertintot1values(7,4,5,5,'g');insertintot1values(6,6,4,4,'f');那么这些数据肯定是存储在文件中的,所以文件中保存这些数据的格式大致如下,顺序和插入顺序一致:4311d1111a8888h2222b5235e3322c7455g6644f注意t1是Innodb的存储引擎,a字段是主键,所以Innodb存储引擎在处理插入的数据时会按主键排序,也就是我上面说的文件中保存这些数据的格式是不准确的,因为我不想太长,所以不想深究。有兴趣的同学可以关注一波公众号:1:25,我会专门写一篇文章来讲解Innodb中索引的具体实现,包括B+树是如何生成的。而如果我们按照上面的存储方式查找数据,比如查找a=3的行,则需要从第一行记录开始查找,那么需要查找6次,如果使用上面的数据按照a字段的大小进行排序:1111a2222b3322c4311d5235e6644f7455g8888h排序后,如果我们还是要查找a=3的记录,只需要查3次就可以了。而且这样做的另一个好处是,如果我们现在需要查找a=3.5的那一行数据,如果按照未排序之前的存储方式,我们需要查询所有8行数据,最后确定出这行数据a=3.5是不存在的,如果我们使用排序存储的方式,只需要检查4次,因为当你找到4311d的记录时,你会发现4>3.5,你已经可以确定a=3.5的记录了不复存在。而如果我们现在在t1上创建一个索引,就像上面创建索引一样,如果我们写下面的sql:createindexidx_t1_bcdont1(b,c,d);这条sql的意思是在t1上建立索引,索引字段为b、c、d,并且升序排列,所以其实就是将原始数据按照b、c、d三个字段进行排序,然后排序后,就是类似:1111a2222b5235e4311d3322c7455g6644f8888h大家可以好好看看,上面的记录都是按照b,c,d三个字段来对数据行进行排序的。比如1111a中b、c、d三个字段的值都是111,而2222b中b、c、d三个字段的值都是222,111小于222,所以相应的行排在第一位。那么这样对数据进行排序有什么好处呢?其实和刚才按a字段排序后的好处差不多。比如你要查找b=4和c=4和d=4的数据,可以查询的更快。其实这就是索引的原理:我们在一个表上建立索引,对表中的数据进行排序,排序后的数据可以提高查询速度。另外需要注意的是,排序的方式有很多种,或者可以使用一些数据结构,比如二叉树、红黑树、B+树等。这些数据结构其实都是对数据进行排序,只是排序形式不同而已。仅此而已,每种数据结构都有自己的特点,大家应该都知道在Mysql中用的最多的还是B+树。相信看到这里大家应该对索引有了新的认识,但是我们上面提到的几个例子都是按升序排序的,排序后的数据不仅可以提高查询速度,还可以为orderby工作。例如,如果我们现在想通过basc,casc,dasc对t1进行排序;对于这个排序,如果t1表中已经建立了b,c,d的升序索引,那么就说明t1表中的数据已经按照b,c,d进行了升序排序,所以对于顺序by语句,可以直接使用排序后的数据,不需要再使用filesort进行排序。而如果我们的orderby是orderbybdesc,cdesc,ddesc,我们也可以使用b,c,d的升序索引,因为如果是orderbybasc,casc,dasc,我们会遍历从上到下。对,如果是bdesc,cdesc,ddesc排序,从下向上遍历即可。那么,如果是basc,cdesc,ddesc排序呢?这个orderby是不是没办法用b,c,d的升序呢?这时候就需要一个降序索引。降序索引的底层实现我们花了很多篇幅介绍了升序索引的实现原理。总结起来就是把表中的数据按照指定的字段比较大小进行升序排序。什么是升序?数据比较后,小的在上,大的在下,或者如果是B+树,小的在左边,大的在右边。降序就是大的在上,小的在下,或者如果是B+树,大的在左边,小的在右边。So,fortheoriginaldataabove:4311d1111a8888h2222b5235e3322c7455g6644fcopycodeIfwesortthisdataaccordingtoadesc:8888h7455g6644f5235e4311d3322c2222b1111aisverysimple,thenifwesortthisdataaccordingtobdesc,cdesc,ddesc:8888h6644f7455g3322c4311d5235e2222b1111aisalsoverysimple,so如果我们想根据bdesc、casc、ddesc对这些数据进行排序怎么办?这有点令人困惑吗?其实并不难。排序其实就是比较数据的大小。我们用下面三行数据来模拟一下:3322c7455g4311d首先按bdesc,cdesc,ddesc排序,结果如下:7455g3322c4311d按bdesc,casc,ddesc排序,结果如下如下:7455g4311d3322c可能有的大佬已经能看懂了,其实bdesc的意思就是b字段的数据越大,数据越小。如果数据相等,则比较c字段,c字段升序排列,即c字段数据小的排在最下面。大的在上面。于是我们得到了上面的结果。这是递减指数。综上所述,实际的升序索引和降序索引只是不同的排序方式。Mysql8实现降序索引后,我们在创建索引的时候就更加灵活了。我们可以根据业务需要的排序规则创建合适的索引,可以让您的查询更快。当然,本文只讲原理。你肯定知道Mysql中用来排序的B+树,不是我上面举例的那种很简单的方式,但是即使你用B+树,原理也是一样的,只是比较数据的大小。还有一点,只有Innodb存储引擎支持降序索引。
