First, there was a typo in the Rank() query: WHERE missing... here it is:
SELECT *
FROM (SELECT T1.*, RANK() OVER (PARTITION BY ALAN8 ORDER BY ALUPMJ DESC) "R"
FROM jdedata910.F0116 T1)
WHERE R = 1;
After setting autotrace I got this results (run the query three times in a row), that I think are not very interesting because the data set is very small...
Test#1 Join Test#2 Join Test#3 Join Test#1 Rank Test#2 Rank Test#3 Rank
SAMPLE 1 0:00:00.14 0:00:00.04 0:00:00.04 0:00:00.07 0:00:00.06 0:00:00.07
recursive calls 1 0 0 1 0 0
db block gets 0 0 0 0 0 0
consistent gets 208 208 208 76 76 76
physical reads 0 0 0 0 0 0
redo size 0 0 0 0 0 0
bytes sent via SQL*Net to client 128479 128479 128479 128387 128387 128387
bytes received via SQL*Net from cli 990 990 990 990 990 990
SQL*Net roundtrips to/from client 59 59 59 59 59 59
sorts (memory) 0 0 0 1 1 1
sorts (disk) 0 0 0 0 0 0
rows processed 860 860 860 860 860 860 of 864 rows
So I switched database and repeated:
SAMPLE 2 0:00:00.74 0:00:00.71 0:00:00.71 0:00:01.59 0:00:01.37 0:00:01.40
recursive calls 0 0 0 10 10 10
db block gets 0 0 0 5 5 5
consistent gets 10187 10186 10186 4531 4531 4531
physical reads 7117 7115 7115 5737 5737 5737
redo size 0 0 0 0 0 0
bytes sent via SQL*Net to client 2793698 2793698 2793698 2600750 2600750 2600750
bytes received via SQL*Net from cli 34107 34107 34107 34107 34107 34107
SQL*Net roundtrips to/from client 3055 3055 3055 3055 3055 3055
sorts (memory) 0 0 0 0 0 0
sorts (disk) 0 0 0 1 1 1
rows processed 45802 45802 45802 45902 45802 45802 of 561840 rows
Rank() is consistently taking almost double with low or medium volume of data, and I think worst, the sort went from memory to disk... I am curious how MAX() in the join query gets the result without sorting -full scan, per address? But RANK() uses less gets and reads: in a busy database will that be an advantage?
So, the winner is... join query (?)
Thank you.
August 29, 2016 - 12:50 am UTC
Interesting results on the larger set (especially the sort going to disk).
Could you run them both with as:
select /*+ GATHER_PLAN_STATISTICS */ ...
from ...
and then run
select * from table(dbms_xplan.display_cursor(null,null,'ALLSTATS LAST'))
I'd be interested in seeing the output for each.
In terms of "who wins" ? Well...(in most cases) priority #1 is response time for the users, so if your second set is representative of the real data, I'd pick the join.