sql >> Base de Datos >  >> RDS >> Oracle

Consideraciones de rendimiento para datos temporales en Oracle

Las tablas temporales son efectivamente las mismas que las tablas en memoria gracias al almacenamiento en caché y la E/S asíncrona, y la solución de tablas temporales no requiere ninguna sobrecarga para convertir entre SQL y PL/SQL.

Confirmación de los resultados

Comparando las dos versiones con RunStats, la versión de la tabla temporal parece mucho peor. Toda esa basura para la versión de la tabla temporal en Run1, y solo un poco de memoria extra para la versión PL/SQL en Run2. Al principio, parece que PL/SQL debería ser el claro ganador.

Type  Name                              Run1 (temp) Run2 (PLSQL)         Diff
----- -------------------------------- ------------ ------------ ------------
...
STAT  physical read bytes                    81,920            0      -81,920
STAT  physical read total bytes              81,920            0      -81,920
LATCH cache buffers chains                  104,663          462     -104,201
STAT  session uga memory                    445,488      681,016      235,528
STAT  KTFB alloc space (block)            2,097,152            0   -2,097,152
STAT  undo change vector size             2,350,188            0   -2,350,188
STAT  redo size                           2,804,516            0   -2,804,516
STAT  temp space allocated (bytes)       12,582,912            0  -12,582,912
STAT  table scan rows gotten             15,499,845            0  -15,499,845
STAT  session pga memory                    196,608   19,857,408   19,660,800
STAT  logical read bytes from cache     299,958,272            0 -299,958,272

Pero al final del día, solo importa la hora del reloj de pared. Tanto los pasos de carga como de consulta se ejecutan mucho más rápido con las tablas temporales.

La versión PL/SQL se puede mejorar reemplazando BULK COLLECT with cast(collect(test_o(MOD(a, 10), '' || MOD(a, 12))) as test_t) INTO t . Pero aún es significativamente más lento que la versión de tabla temporal.

Lecturas optimizadas

La lectura de la pequeña tabla temporal solo usa el caché del búfer, que está en la memoria. Ejecute solo la parte de la consulta muchas veces y observe cómo el consistent gets from cache (memoria) aumenta mientras el physical reads cache (disco) permanece igual.

select name, value
from v$sysstat
where name in ('db block gets from cache', 'consistent gets from cache', 
'physical reads cache');

Escrituras optimizadas

Idealmente, no habría E/S física, especialmente porque la tabla temporal es ON COMMIT DELETE ROWS . Y parece que la próxima versión de Oracle puede introducir dicho mecanismo. Pero no importa mucho en este caso, la E/S del disco no parece ralentizar las cosas.

Ejecute el paso de carga varias veces y luego ejecute select * from v$active_session_history order by sample_time desc; . La mayor parte de la E/S es BACKGROUND , lo que significa que no hay nada esperando. Supongo que la lógica interna de la tabla temporal es solo una copia de los mecanismos DML regulares. En general, los nuevos datos de la tabla pueden debe escribirse en el disco, si está confirmado. Oracle puede comenzar a trabajar en ello, por ejemplo, moviendo datos del búfer de registro al disco, pero no hay prisa hasta que haya un COMMIT real. .

¿Adónde va el tiempo de PL/SQL?

No tengo ni idea. ¿Hay varios cambios de contexto o una única conversión entre los motores SQL y PL/SQL? Que yo sepa, ninguna de las métricas disponibles muestra el tiempo gastado en cambiar entre SQL y PL/SQL.

Es posible que nunca sepamos exactamente por qué el código PL/SQL es más lento. No me preocupo demasiado por eso. La respuesta general es que la gran mayoría del trabajo de la base de datos debe realizarse en SQL de todos modos. Tendría mucho sentido si Oracle dedicara más tiempo a optimizar el núcleo de su base de datos, SQL, que el lenguaje complementario, PL/SQL.

Notas adicionales

Para las pruebas de rendimiento, puede ser útil eliminar connect by lógica en un paso separado. Ese SQL es un gran truco para cargar datos, pero puede ser muy lento y consumir muchos recursos. Es más realista cargar una tabla de muestra una vez con ese truco y luego insertar desde esa tabla.

Intenté usar la nueva función Oracle 12c, deshacer temporal, y la nueva función 18c, tablas temporales privadas. Ninguno mejoró el rendimiento con respecto a las tablas temporales normales.

No apostaría por ello, pero puedo ver una forma en que los resultados cambiarían por completo a medida que los datos aumentan. El búfer de registro y la memoria caché del búfer solo pueden llegar a ser tan grandes. Y eventualmente esa E/S de fondo podría acumularse y abrumar algunos procesos, convirtiendo el BACKGROUND espera en un FOREGROUND Espere. Por otro lado, solo hay cierta cantidad de memoria PGA para la solución PL/SQL y luego las cosas fallan.

Finalmente, esto confirma parcialmente mi escepticismo sobre las "bases de datos en memoria". El almacenamiento en caché no es nada nuevo, las bases de datos lo han estado haciendo durante décadas.