Depuis que j'ai fait une comparaison de Chad's et Nick's approches pour faire un commentaire sur la réponse de Nick, je pensais que je posterais mes résultats ici. Je paquet de Tom Kyte runstats pour les comparer avec ce script:
begin
runstats_pkg.rs_start('Chad');
for i in 1..10000 loop
for r in (
SELECT EMPLID,EFFDT,ACTION,ACTION_REASON
FROM (SELECT ROWNUM rnum, EMPLID,EFFDT,ACTION,ACTION_REASON
FROM (SELECT EMPLID,EFFDT,ACTION,ACTION_REASON
FROM JOB
WHERE emplid = '12345')
WHERE rownum <= 60
)
WHERE rnum >= 50
) loop
null;
end loop;
end loop;
runstats_pkg.rs_middle('Nick');
for i in 1..10000 loop
for r in (
select EMPLID, EFFDT, ACTION, ACTION_REASON
from
(
SELECT EMPLID, EFFDT, ACTION, ACTION_REASON, row_number() over (order by emplid) rn
from JOB where emplid ='12345'
)
where rn between 50 and 60
) loop
null;
end loop;
end loop;
runstats_pkg.rs_stop(0,false,false,false,false,false,false,false,false);
end;
/
Les résultats:
Run1 = Chad
Run2 = Nick
*** Comparative Time Report ***
Run Time (hsecs)
--------------------------------------------------
Run1 69
Run2 77
Run1 ran in 89.61% of the time of Run2
Run2 ran in 111.59% of the time of Run1
PL/SQL procedure successfully completed.
Utilisation autotrace les plans peuvent être vu être assez similaire:
SQL> SELECT EMPLID,EFFDT,ACTION,ACTION_REASON
2 FROM (SELECT ROWNUM rnum, EMPLID,EFFDT,ACTION,ACTION_REASON
3 FROM (SELECT EMPLID,EFFDT,ACTION,ACTION_REASON
4 FROM JOB
5 WHERE emplid = '12345')
6 WHERE rownum <= 60
7 )
8 WHERE rnum >= 50
9/
no rows selected
Execution Plan
----------------------------------------------------------
------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 41 | 3 (0)|
|* 1 | VIEW | | 1 | 41 | 3 (0)|
|* 2 | COUNT STOPKEY | | | | |
| 3 | TABLE ACCESS BY INDEX ROWID| JOB | 1 | 13 | 3 (0)|
|* 4 | INDEX RANGE SCAN | JOB2_PK | 1 | | 2 (0)|
------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("RNUM">=50)
2 - filter(ROWNUM<=60)
4 - access("EMPLID"=12345)
Statistics
----------------------------------------------------------
1 recursive calls
0 db block gets
2 consistent gets
0 physical reads
0 redo size
264 bytes sent via SQL*Net to client
231 bytes received via SQL*Net from client
1 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
0 rows processed
SQL> select EMPLID, EFFDT, ACTION, ACTION_REASON
2 from
3 (
4 SELECT EMPLID, EFFDT, ACTION, ACTION_REASON, row_number() over (order by emplid) rn
5 from JOB where emplid ='12345'
6 )
7 where rn between 50 and 60
8/
no rows selected
Execution Plan
----------------------------------------------------------
------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 41 | 3 (0)|
|* 1 | VIEW | | 1 | 41 | 3 (0)|
|* 2 | WINDOW NOSORT STOPKEY | | 1 | 17 | 3 (0)|
| 3 | TABLE ACCESS BY INDEX ROWID| JOB | 1 | 17 | 3 (0)|
|* 4 | INDEX RANGE SCAN | JOB2_PK | 1 | | 2 (0)|
------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("RN">=50 AND "RN"<=60)
2 - filter(ROW_NUMBER() OVER (ORDER BY "EMPLID")<=60)
4 - access("EMPLID"=12345)
filter("EMPLID"=12345)
Statistics
----------------------------------------------------------
1 recursive calls
0 db block gets
2 consistent gets
0 physical reads
0 redo size
264 bytes sent via SQL*Net to client
231 bytes received via SQL*Net from client
1 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
0 rows processed
Il Il semblerait qu'il n'y ait pas beaucoup à choisir entre les 2 méthodes, bien que le Tchad soit toujours légèrement plus rapide sur ma base de données qui est:
Oracle Database 10g version 10.2.0.3.0 - 64bit Production
Merci Nick, ça a marché. J'apprécie vraiment votre aide. –
Pas vrai: juste parce qu'il ressemble à une requête dans une requête dans une requête, cela ne signifie pas qu'Oracle l'implémente comme ça. J'ai juste testé chaque méthode 10 000 fois et ils ont fonctionné en 69 et 78 ms (le vôtre était le plus lent, mais la différence est insignifiante). Expliquer Le plan montre ce qui se passe –
Sur mon système, les temps sont insignifiants dans la plage de 1,5 ms de ma table, mais la syntaxe de row_number est plus propre et ne nécessite pas deux vues en ligne. Voir Tom Kyte, http://www.oracle.com/technology/oramag/oracle/07-jan/o17asktom.html – Nick