ROW_NUMBER
es bastante ineficiente en Oracle
.
Ver el artículo en mi blog para los detalles de rendimiento:
Para su consulta específica, me gustaría recomendar que reemplazarlo con ROWNUM
y asegurarse de que se utiliza el índice :
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
Esta consulta utilizará COUNT STOPKEY
También, o bien asegúrese de que column
no sea nulo, o agregue la condición WHERE column IS NOT NULL
.
De lo contrario, el índice no se puede utilizar para recuperar todos los valores.
Tenga en cuenta que no puede usar ROWNUM BETWEEN :start and :end
sin una subconsulta.
ROWNUM
siempre se asigna al último y se marca el último, así es ROWNUM
siempre vienen en orden sin espacios.
Si utiliza ROWNUM BETWEEN 10 and 20
, la primera fila que satisifies todas las demás condiciones se convertirá en un candidato para el retorno, asignado temporalmente con ROWNUM = 1
y no pasan la prueba de ROWNUM BETWEEN 10 AND 20
.
Luego, la siguiente fila será candidata, se le asignará ROWNUM = 1
y se producirá un error, etc., por lo que, finalmente, no se devolverán las filas.
Esto debería solucionarse poniendo ROWNUM
en la subconsulta.
Funciona como una Sin embargo, las sugerencias del optimizador no parecían hacer una diferencia apreciable. –
Eso significa que "CBO" fue lo suficientemente inteligente como para recoger los índices. En realidad, era ROWNUM en lugar de ROW_NUMBER lo que importaba aquí. – Quassnoi
Pero aún dejaría las pistas o crearía un BOSQUEJO, en caso de que la CBO cambiara de opinión :) – Quassnoi