ROW_NUMBER
est très inefficace dans Oracle
.
Voir l'article dans mon blog pour plus de détails de performance:
Pour votre requête spécifique, je vous recommande de le remplacer par ROWNUM
et assurez-vous que l'indice est utilisé :
SELECT *
FROM (
SELECT /*+ INDEX_ASC(t index_on_column) NOPARALLEL_INDEX(t index_on_column) */
t.*, ROWNUM AS rn
FROM table t
ORDER BY
column
)
WHERE rn >= :start
AND rownum <= :end - :start + 1
Cette requête utilisera COUNT STOPKEY
Également soit assurez-vous que column
n'est pas NULL, ou ajouter WHERE column IS NOT NULL
condition.
Sinon, l'index ne peut pas être utilisé pour récupérer toutes les valeurs.
Notez que vous ne pouvez pas utiliser ROWNUM BETWEEN :start and :end
sans sous-requête.
ROWNUM
est toujours affecté dernière et vérifié dernière, que son chemin ROWNUM
« s viennent toujours pour sans lacunes.
Si vous utilisez ROWNUM BETWEEN 10 and 20
, la première ligne qui satisfait toutes les autres conditions deviendra candidate au renvoi, affectée temporairement à ROWNUM = 1
et échouera au test ROWNUM BETWEEN 10 AND 20
.
Ensuite, la ligne suivante sera candidate, affectée de ROWNUM = 1
et échouera, etc., donc, finalement, aucune ligne ne sera renvoyée du tout.
Cela devrait être contourné en mettant ROWNUM
dans la sous-requête.
Fonctionne comme un Cependant, les conseils de l'optimiseur ne semblaient pas faire une différence appréciable: –
Cela signifiait que CBO était assez intelligent pour récupérer les index, mais que c'était ROWNUM plutôt que ROW_NUMBER qui importait ici. – Quassnoi
Mais je laisserais toujours les conseils ou créer un PLAN, juste au cas où le CBO changera d'avis :) – Quassnoi