SQL优化(二)

order by排序方式

一般分两种,在索引中排序(索引里面数据有序),在内存中排序(内存不够的话会产生临时文件辅助排序)。其中走索引的排序会快很多。

索引排序

既然我们知道排序走索引会快很多,那我们排序时应该尽量让排序走索引。那什么情况下排序会走索引呢?我们知道查询排序语句一般由这几个部分构成:select +where+order by+limit…等等。所以SQL走不走索引主要由这几部分的限制决定。一般查询排序语句是先将排序的几列和id从数据库读出进行排序,排序完成后再根据id去表中查询select的列,最后返回客户端结果集。因为索引中的数据是有序的,排序的列和查询的列同时在一个索引中,并且顺序是相同的,就可以直接从索引中读出这几列返回给客户端。

例子

下面是t3表建表语句
在这里插入图片描述

  • 查询语句是select idc,name from t3 order by idc,因为查询和排序的字段存在索引
    idx_idc_name_id,所以会走索引。
  • 查询语句是select idc,name,nickname from t3 order by idc,因为不存索引同时包含idc,name,nickname,所以不会走索引。
  • 查询语句是select idc,name from t3 order by idc,name,因为查询和排序的存在索引
    idx_idc_name_id,所以会走索引。
  • 查询语句是select idc,name from t3 order by name,因为排序的字段是name,没有以这个字段为顺序的索引,所以不会走索引。
  • 查询语句是select idc,name,id from t3 order by idc,id,因为排序的字段是idc和id,没有以这两个字段为顺序的索引(索引idx_idc_name_id里面的排序顺序是按照idc,name,id来排序的),所以排序不会走索引,但是查询会走索引(会先在内存中将idc,id两个字段排序好,再根据id去查询select需要的字段,因为查询的字段存在索引idx_idc_name_id,所以直接再索引中得到id相对应的字段)。
  • 查询语句是select name,id from t3 order by idc,因为查询和排序的存在索引
    idx_idc_name_id,所以会走索引。
  • 查询语句是select id,name from t3 order by id,因为排序的存在主键,所以会走主键。
  • 查询语句是select idc,name from t3 order by idc,name,因为查询和排序的存在索引idx_idc_name_id,所以会走索引。
  • 查询语句是select id,name from t3 where idc=3 order by idc,因为排序和查询字段存在索引idx_idc_name_id,所以会走索引。
  • 查询语句是select id,name from t3 where idc=3 order by name,虽然不存在以name为顺序的索引,但是!!!where idc=3这个条件,限制了idc是相同的,当idc相同时,索引 idx_idc_name_id就是按照name排序的,因此这个语句依然会走索引。
    在这里插入图片描述
  • 查询语句是select id,name from t3 where idc>2 order by name,虽然where语句限定了idc>2这个条件,将数据分为了两部分>2,<=2。但是索引idx_idc_name_id是先按照idc排序,再按照name,最后按id排序,而我们的排序是只按照name,idc>2的数据里面id也是不一样的,所以没有走索引。
    在这里插入图片描述

非索引排序

当没有走索引的时候,MySQL内部会有三种排序实现分别是常规排序优化排序优先队列排序。主要涉及三种排序算法快速排序归并排序堆排序

常规排序

常规排序使用的排序算法是快速排序!
MySQL会先把符合where限定的行筛选出来,然后读出排序的字段+主键到内存中(sort buffer),如果sort buffer满了,会写入临时文件中进行排序。排序完后根据主键去筛选出来的行中读出select需要的字段形成结果集返回给客户端。

优化排序

常规排序除了排序所消耗的时间外,还有两次io(第一次是读出排序的列和主键,第二次是排序完后根据主键去读select的列),这也会造成时间的消耗,所以就有了优化排序。优化排序是一次行将排序列和select列都读入sort buffer中,排序完后直接将结果集方会给客户端,减少了第二次io造成的时间开销,但是因为需要的内存较大,经常会产生临时文件(如果很多个临时文件,还会使用归并排序)。

优先队列排序

5.6版本的MySQL产生了优先队列排序实现,采用堆排序,对于升序采用最大堆,降序采用最小堆。
但是limit有时会产生分页重复(再MySQL8中被修复),因为堆排序是非稳定的,对于相同的key无法保证排序前后位置一致。

总结

对select字段,where条件,order字段进行设计,尽可能的让排序走索引。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值