Si estás involucrado en un proyecto que se base en una base de datos crítica y muy usada, o si estás involucrado en temas de pruebas de carga y estrés, el mantenimiento de datos es un tema con el que te encontrarás antes o después.

Cuando intentas ejecutar un simple DELETE FROM ... WHERE... y la clausula WHERE involucra a muchas filas corres el peligro de que la Base de Datos se quede sin espacio para el "buffer" de la transacción. En estas situaciones puedes aplicar el siguiente proceso de dos pasos:

  • Obtener las filas a borrar
  • Borrar las filas una a una, limitando el número de filas borradas en cada transacción

Veamos un ejemplo sobre Oracle.

La obtención de filas a borrar puede ser bastante costosa dependiendo de la condición indicada en la cláusula WHERE, pero en los deletes generados las condiciones WHERE usan la columna ROWID y por ello se ejecutan mucho más rápido.

Paso 1: Obtener las filas a borrar

Este paso se realiza redirigiendo la salida (spool en SQLPlus) de un script como el siguiente a un fichero sql. Nota: Este script no contiene aun los agrupamientos en bloques.

prompt prompt DELETE user.table_name ...
SELECT  'DELETE user.table_name WHERE rowid='''||table_name.rowid||''';'
FROM user.table_name, ...
WHERE ... -- complex condition;

Preparación de los bloques

Puedes hacer esto con las funciones MOD y DECODE.

prompt prompt DELETE user.table_name ...
SELECT 'DELETE user.table_name 
WHERE rowid='''||table_name.rowid||''';'||
    DECODE(MOD(ROWNUM,1000),0,CHR(10)||CHR(13)||'COMMIT;',NULL)
FROM user.table_name, ...
WHERE ... -- complex condition;
prompt COMMIT;

La función DECODE implementa una condición tipo if de forma que cuando el resto de ROWNUM entre 1000 es cero entonces se inserta una línea COMMIT, que empieza una transacción nueva automáticamente (es decir, cada 1000 líneas pero esto se puede ajustar a las necesidades de tu escenario concreto).

...
DELETE user.table_name WHERE rowid='AAAAACAABAAATNWAAB';
DELETE user.table_name WHERE rowid='AAAJWTAAWAAB+BiAAC';
COMMIT;
DELETE user.table_name WHERE rowid='AAAKPkAAKAAARs7AAC';
...

Paso 2: Borrado de las filas una a una:

Se realiza ejecutando el script resultado del paso 1.

Almacenado en: lenguajes, infraestructura

comentarios

No hay ningún comentario.