A reader, March 26, 2018 - 6:11 am UTC
I will try to give you an example as soon as possible. Until then, It's something that doesn't make sense for me:
An analytic function isn't processed before the query's order by? In my example
select rownum, i.* from (
select row_number() over (order by null) as rnum, i.*
from invoice i
order by i.dateinvoiced desc
) i
if I replace "order by i.dateinvoiced desc" with asc or another column row_number() still gives 1, 2, 3...
From this tests It seems that row_number() is processed after order by...
Also, to give a more concise answer to the initial question (if it's safe to replace rownum with row_number() over (order by null)), my personal opinion is that this is just a coincidence (a side effect of an oracle internal algorithm). What do you think?
March 27, 2018 - 5:24 am UTC
"It seems that row_number() is processed after order by... "
I think a more likely hypothesis is that we simply optimize it out, ie, conceptually treat it like rownum.
But it will stress, I can't find anything in the docs that says the two are synonymous...so it might change one day.
The only thing we have in there is:
"the order in which nulls are presented is non-deterministic."
Ionut Ursuleanu, March 26, 2018 - 10:32 am UTC
Function call?
John Keymer, March 27, 2018 - 7:30 am UTC
In your example, you select a function value. Is that what is happening in the real query? Is that function passed a value if so? Could it be that the function is being called for every row and would benefit from Scalar Subquery Caching?
i.e. use (select myFunction() from dual) instead.
I ran both your examples on 12.1 and they both returned instantly as expected given the small data volumes. Were you comparing the plan cost? Even though they are very similar, I'd imagine that you cannot do that because ultimately they are different queries.
March 28, 2018 - 1:45 am UTC
Sorry, I can't reproduce that. This from 11.2.0.4 (Windows)
<code>
SQL> set timing on
SQL> begin
2 for i in (
3 select rownum, t1.* from (
4 select t.*
5 from t
6 order by t.x
7 ) t1
8 )
9 loop
10 null;
11 end loop;
12 end;
13 /
PL/SQL procedure successfully completed.
Elapsed: 00:00:05.97
SQL> /
PL/SQL procedure successfully completed.
Elapsed: 00:00:06.08
SQL> /
PL/SQL procedure successfully completed.
Elapsed: 00:00:05.72
SQL> /
PL/SQL procedure successfully completed.
Elapsed: 00:00:05.72
SQL>
SQL>
SQL> set timing on
SQL> begin
2 for i in (
3 select row_number() over (order by null) as rnum, t.*
4 from t
5 order by t.x
6 )
7 loop
8 null;
9 end loop;
10 end;
11 /
PL/SQL procedure successfully completed.
Elapsed: 00:00:06.56
SQL> /
PL/SQL procedure successfully completed.
Elapsed: 00:00:06.64
SQL> /
PL/SQL procedure successfully completed.
Elapsed: 00:00:06.63
SQL> /
PL/SQL procedure successfully completed.
Elapsed: 00:00:06.63
SQL>
SQL>
SQL>
</code
Ionut Ursuleanu, March 27, 2018 - 9:28 am UTC
I also tested the queries with 12.2 and ran below 0.5s. BUT, in 11.2.0.4 the rownum takes 2.7s