今天无意间看了一个文章,文章里这个面试官说他在面试的时候一般都会问两个问题:
1.order by和rownum执行顺序的问题
2.union和union all的区别
union和union all的区别这个我知道,区别在于去不去重(这个地方有问题,下面说),order by和rownum执行顺序的问题这个我还真不知道,所以说想研究一下
网上查了一下。比较靠谱的说法是order by涉及到索引列的先order by再rownum,order by涉及到普通列的话先rownum再order by
然后实际测试一下发现,上面的描述也不对。
那么如何来确认order by和rownum的执行顺序呢,我在测试过程中突然想到了一个思路,那就是看执行计划。
给大家贴两个执行计划,大家就看明白了(我这是plsql里面F5生成的执行计划,不一定是sql的真正的执行计划)
看到区别了么,尤其是红框部分:
第一个走的是index full scan,然后count stopkey,众所周知索引是有序的,且count stopkey其实就是sql的rownum操作,所以说第一个sql是先进行的order by,再进行的rownum
第二个走的是 table access full,然后count stopkey,然后sort order by,这就更明确了,先全表扫,再rownum,再order by
所以当遇到这种情况,我们只能通过看执行计划来确定,没有什么万能的规律。
所以说我们SQL里面如果想写成先order by再rownum的逻辑,最好的方式就是使用row_number() over (order by xxx)加嵌套查询的模式。
在上面的实验过程后我顺便看了一下union和union all的执行计划,我发现了一个情况,那就是union的sql的执行计划的最外层有一个sort unique操作!! 也就是说union就相当于是union all+sort unique,也就是说union是union all的基础上加去重加默认排序
执行计划看这图: