ROW_NUMBER
è abbastanza inefficiente in Oracle
.
vedere l'articolo nel mio blog per i dettagli delle prestazioni:
Per la vostra domanda specifica, vi consiglio di sostituire con ROWNUM
e assicurarsi che l'indice è utilizzato :
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
Questa query utilizzerà COUNT STOPKEY
Inoltre, assicurati di non avere il valore n. column
o aggiungere la condizione WHERE column IS NOT NULL
.
In caso contrario, non è possibile utilizzare l'indice per recuperare tutti i valori.
Nota che non è possibile utilizzare ROWNUM BETWEEN :start and :end
senza subquery.
ROWNUM
viene sempre assegnato per ultimo e controllato per ultimo, in questo modo ROWNUM
vengono sempre ordinati senza interruzioni.
Se si utilizza ROWNUM BETWEEN 10 and 20
, la prima riga che soddisfa tutte le altre condizioni diventerà un candidato per la restituzione, temporaneamente assegnata con ROWNUM = 1
e non riuscirà il test di ROWNUM BETWEEN 10 AND 20
.
Quindi la riga successiva sarà un candidato, assegnato con ROWNUM = 1
e non riuscito, ecc., Quindi, infine, non verrà restituita alcuna riga.
Questo dovrebbe essere risolto inserendo ROWNUM
nella sottoquery.
Funziona come un Tuttavia, i suggerimenti per l'ottimizzazione non sembrano fare una differenza apprezzabile: –
Ciò significa che 'CBO' era abbastanza intelligente da raccogliere gli indici.In realtà era ROWNUM invece ROW_NUMBER che contava qui. – Quassnoi
Ma vorrei ancora lasciare i suggerimenti o creato una struttura, nel caso in cui il CBO cambierà idea :) – Quassnoi