ROW_NUMBER är ganska ineffektivt i Oracle .
Se artikeln i min blogg för information om prestanda:
- Oracle:ROW_NUMBER kontra ROWNUM
För din specifika fråga rekommenderar jag att du ersätter den med ROWNUM och se till att indexet används:
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
Den här frågan använder COUNT STOPKEY
Se också antingen till att du column är inte nullbar, eller lägg till WHERE column IS NOT NULL skick.
Annars kan indexet inte användas för att hämta alla värden.
Observera att du inte kan använda ROWNUM BETWEEN :start and :end utan en underfråga.
ROWNUM är alltid tilldelad sist och markerad sist, det är så ROWNUM har alltid kommit i ordning utan luckor.
Om du använder ROWNUM BETWEEN 10 and 20 , den första raden som uppfyller alla andra villkor kommer att bli en kandidat för retur, tillfälligt tilldelad ROWNUM = 1 och misslyckas i testet ROWNUM BETWEEN 10 AND 20 .
Då kommer nästa rad att vara en kandidat, tilldelad ROWNUM = 1 och misslyckas, etc., så slutligen kommer inga rader att returneras alls.
Detta bör lösas genom att sätta ROWNUM är i underfrågan.