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.