ORDER BY 一般会有两种实现方法,一个是利用有序索引自动实现,也就是说利用有序索引的有序性就再也不另作排序操做了。另外一个是把结果选好以后再排序。数据库
用有序索引这种,固然是最快的,不过有一些限制条件,来看下面的测试。 性能
测试数据:student表有两个字段id ,sid ,id是主键。一共有20W条记录,id从1到200000,sid也是从1到200000的数据。 测试
第一种状况 : 排序
order by的字段不在where条件也不在select中 索引
select sid from zhuyuehua.student where sid < 50000 order by id;内存
第二种状况 :资源
order by的字段不在where条件但在select中。 io
select id,sid from zhuyuehua.student where sid < 50000 order by id;select
第三种状况 : nio
order by的字段在where条件但不在select中。
select sid from zhuyuehua.student where sid < 50000 and id < 50000 order by id;
第四种状况 :
order by的字段在where条件但不在select中。倒序排列
select sid from zhuyuehua.student where sid < 50000 and id < 50000 order by id desc;
测试结果:
order by的字段不在where条件不在select中 有排序操做
order by的字段不在where条件但在select中 有排序操做
order by的字段在where条件但不在select中 无排序操做
order by的字段在where条件但不在select中(倒序) 无排序操做
结论:
当order by 字段出如今where条件中时,才会利用索引而无需排序操做。其余状况,order by不会出现排序操做。
分析:
为何只有order by 字段出如今where条件中时,才会利用该字段的索引而避免排序。这要说到数据库如何取到咱们须要的数据了。
一条SQL实际上能够分为三步。
1.获得数据
2.处理数据
3.返回处理后的数据
好比上面的这条语句select sid from zhuyuehua.student where sid < 50000 and id < 50000 order by id desc
第一步:根据where条件和统计信息生成执行计划,获得数据。
第二步:将获得的数据排序。
当执行处理数据(order by)时,数据库会先查看第一步的执行计划,看order by 的字段是否在执行计划中利用了索引。若是是,则能够利用索引顺序而直接取得已经排好序的数据。若是不是,则排序操做。
第三步:返回排序后的数据。
另外:
上面的5万的数据sort只用了25ms,也许你们以为sort不怎么占用资源。但是,因为上面的表的数据是有序的,因此排序花费的时间较少。若是 是个比较无序的表,sort时间就会增长不少了。另外排序操做通常都是在内存里进行的,对于数据库来讲是一种CPU的消耗,因为如今CPU的性能加强,对 于普通的几十条或上百条记录排序对系统的影响也不会很大。可是当你的记录集增长到上百万条以上时,你须要注意是否必定要这么作了,大记录集排序不只增长了 CPU开销,并且可能会因为内存不足发生硬盘排序的现象,当发生硬盘排序时性能会急剧降低。
注:ORACLE或者DB2都有一个空间来供SORT操做使用(上面所说的内存排序),如ORACLE中是用户全局区(UGA),里面有SORT_AREA_SIZE等参数的设置。若是当排序的数据量大时,就会出现排序溢出(硬盘排序),这时的性能就会下降不少了。
总结:
当order by 中的字段出如今where条件中时,才会利用索引而不排序,更准确的说,order by 中的字段在执行计划中利用了索引时,不用排序操做。
这个结论不只对order by有效,对其余须要排序的操做也有效。好比group by 、union 、distinct等。