Oracle 10g: Posible optimización de volcado masivo de datos

 

En Oracle SQL, se pueden optimizar ejecuciones batch que hagan un volcado masivo de datos en una misma tabla usando sentencias de insert o update por registro dentro de un bloque. Se pueden optimizar con el uso de parámetros (si el cliente lo permite) o si usamos odbc con bind variables.

Recordemos los pasos que sigue Oracle para procesar una consulta:

  1. Validación Sintáctica
  2. Validación Semántica
  3. Optimización
  4. Generación del QEP (Query Execution Plan)
  5. Ejecución del QEP (Query Execution Plan)

Las sentencias SQL pueden recoger los parámetros por valor (where salario>1000) o una vez compilada la sentencia haciendo uso de Bind Variables (where salario>:b1). La ventaja de la segunda opción es que Oracle compila un única vez la sentencia y reutiliza el código compilado para cada uno de los valores para los parámetros. Pero hay que ir con ojo ya que en este segundo caso, Oracle no puede calcular el grado de selectividad de una consulta y, en su lugar, aplica un grado de selectividad por defecto (asociado a cada tipo de operación), lo cual puede dar lugar a decisiones "equivocadas".

Por lo tanto, trabajando por costes es desaconsejable el uso de Bind Variables, salvo que trabajemos con sentencias Oracle SQL que se van a ejecutar repetidas veces y que no ofrezcan muchas dudas en cuanto a los posibles planes de acceso que puede generar.

En casos probados como el siguiente el tiempo de ejecución se reduce hasta en un 90% en una inserción de 100.000 registros...

 

SQL para Creación de la tabla necesaria para la prueba:

create table PRUEBA
(
 NUM number(22),
 TEXTO varchar(100)
);

 

SQL de Carga con parámetros por valor:

declare
 v_i number;
begin
 loop
 INSERT INTO PRUEBA VALUES (3, '50'); 
 v_i := v_i + 1;
 exit when v_i > 1000000;
 end loop;
rollback;
end;

 

SQL de Carga con parámetros usando bind variables

declare
 v_i number;
begin
 loop
 execute immediate 'INSERT INTO PRUEBA VALUES (:x, :y)' using 3, '50'; 
 v_i := v_i + 1;
 exit when v_i > 1000000;
 end loop;
rollback;
end;

Adjunto los resultados de la prueba realizada antes de aplicar cambios en producción (un viernes por la tarde )

 

FILAS POR VALOR CON BIND VARIABLES
10000 5,3350 0,4370
100000 58,5160 6,1000
1000000 (A)570,1060 (B)54,1950