Foros del Web » Programación para mayores de 30 ;) » Bases de Datos General » Oracle »

Borrado masivo

Estas en el tema de Borrado masivo en el foro de Oracle en Foros del Web. Hola. Tengo un pequeño problema, que mas bien es una pequeña indecisión. Necesito hacer un borrado masivo de datos en una tabla usando las referencias ...
  #1 (permalink)  
Antiguo 23/02/2010, 04:40
 
Fecha de Ingreso: marzo-2005
Mensajes: 189
Antigüedad: 15 años, 8 meses
Puntos: 0
Borrado masivo

Hola.

Tengo un pequeño problema, que mas bien es una pequeña indecisión.
Necesito hacer un borrado masivo de datos en una tabla usando las referencias de otra tabla. Como se que esto solo lo he entendido yo, voy a explicarmen mejor:

Mas o menos estas son las tablas

TABLA1
----------
ID number
ID_TABLA2 number


TABLA2
-------------
ID number
FECHA date

index(id)


Y el borrado que necesito hacer, en bruto seria algo como:

DELETE FROM TABLA1 WHERE ID IN
(SELECT ID FROM TABLA2 WHERE FECHA='1/01/2010');

Obviamente esta no me vale porque son millones de registros a borrar.
He buscado muchas formas diferentes de hacerlo, algunos scripts que he encontrado para mi son incomprensibles

El último que he visto es usando el paquete DBMS_REDEFINITION. Pero tras darle muchas vueltas aún no se seguro si podria valerme o no.
Donde mas dudo es a la hora de crear la tabla con CTAS. No se si crearla vacia y luego hacer el insert de los datos con el /*+append*/, nologging y demás. O crearla con todos los datos pero excluyendo los que quiero borrar.

El principal problema que tengo, es que mi entorno de pruebas es como 100 veces mas pequeño que el entorno de producción, por eso no me sirve de mucho probar aqui.

¿teneis alguna sugerencia ya sea de el método que comento o de algun otro?

Gracias y un saludo
  #2 (permalink)  
Antiguo 23/02/2010, 05:09
 
Fecha de Ingreso: junio-2007
Mensajes: 891
Antigüedad: 13 años, 5 meses
Puntos: 43
Respuesta: Borrado masivo

No estoy seguro, pero creo que ese paquete opera sobre la totalidad de la tabla, no sobre parte de ella.
Mi consejo es que tires de un INSERT.... SELECT de los datos buenos y luego borres la original , renombres la temporal y crees de nuevo indices y demas.......
Si encuentras una ventana nocturna para hacerlo, dejas preparado un sql para que se ejecute por la noche y por la mañana ya lo tienes. De todas maneras no te aconsejo eso, si hay algún error la cagas bien cagada, mejor hazlo cuando puedas monitorizarlo sin afectar al on-line.

¿ de cuantos millones de registros para borrar y para dejar estamos hablando ? ¿ tamaño total de la tabla y totalidad de registros ?
  #3 (permalink)  
Antiguo 23/02/2010, 10:34
 
Fecha de Ingreso: marzo-2005
Mensajes: 189
Antigüedad: 15 años, 8 meses
Puntos: 0
Respuesta: Borrado masivo

Efectivamente. Ya habia valorado ese método pero me parecia demasiado engorroso y arriesgado.

La tabla en producción, podria tener 20 0 30 millones de registros, de los que a lo mejor necesitaria eliminar 2 o 3. No puedo saberlo con exactitud pero los números deben andar por ahí...

Estoy pensando en hacer un bucle que elimine los registros uno por uno y ejecute un commit cada 100000 registros, por ejemplo. Pero tengo algunas dudas:

Se que no puedo usar un cursor porque necesita un snapshot de toda la tabla. Asíque estoy pensando en meter todos los ID en una tabla temporal o un array, para ir recorriendolos y ejecutando el delete de la otra tabla tomando este valor ID como referencia. ¿como funcionaria un array con millones de registros? ¿ocuparian toda la memoria?

La otra opción es usar una tabla, temporal o no. La mecánica del script seria algo parecido a esto:


-- tendria una tabla t_temp con todos los Id.

SELECT COUNT(*) INTO REGISTROS FROM tabla_t;

LOOP
EXIT WHEN CONTADOR =0;
DELETE FROM tabla1 WHERE id IN
(SELECT id_tabla1 FROM t_temp WHERE rowcount < 100000);

IF REGISTROS >= 100000 THEN
COMMIT;
REGISTROS := 0;
END IF;

FROM t_temp WHERE ROWCOUNT < 100000';
SELECT COUNT(*) INTO CONTADOR FROM t_temp;

END LOOP;


Aunque claro, aún tengo que conseguir que funcione. De entrada me está dando problemas con el rowcount.

Última edición por Alextroy; 23/02/2010 a las 10:51
  #4 (permalink)  
Antiguo 24/02/2010, 01:14
 
Fecha de Ingreso: junio-2007
Mensajes: 891
Antigüedad: 13 años, 5 meses
Puntos: 43
Respuesta: Borrado masivo

No, no, olvidate de eso. Te estás ahogando en un vaso de agua.

Tira directamente un delete y olvidate del tema. Pensaba que hablabas de 200-300 millones de registros.
Un delete de 3 millones sobre un total de 30 te va a tardar un par de minutos como mucho ( si llega )
  #5 (permalink)  
Antiguo 24/02/2010, 01:34
 
Fecha de Ingreso: marzo-2005
Mensajes: 189
Antigüedad: 15 años, 8 meses
Puntos: 0
Respuesta: Borrado masivo

En realidad lo del tiempo que tarde me preocupa menos. Me preocupa mas que genere mucho UNDO y que me salte el temido ORA-01555.

Claro que estoy tratando el DELETE como si fuese un UPDATE en cuanto a generación de UNDO se re refiere... Pero si me dices que puedo lanzar un borrado de 3 o 4 millones, entiendo que estoy equivocado ¿no?. Porque si fuese un update, a partir de los 50000 o 60000 registros ya me está saltando el error...
  #6 (permalink)  
Antiguo 24/02/2010, 03:14
 
Fecha de Ingreso: junio-2007
Mensajes: 891
Antigüedad: 13 años, 5 meses
Puntos: 43
Respuesta: Borrado masivo

Nada tan facil como probar.

Tu simplemente tira el delete a pelo, ya veras como no tienes problemas. Para que no te salte el 1555, fuerzale a que te use un segmento de rollback especifico y grande .
  #7 (permalink)  
Antiguo 24/02/2010, 04:25
 
Fecha de Ingreso: marzo-2005
Mensajes: 189
Antigüedad: 15 años, 8 meses
Puntos: 0
Respuesta: Borrado masivo

Vaya, eso sique es nuevo para mi...

Si no es demasiado pedir ya. Me puedes comentar un poco eso de forzarle a usar un segmento de rollback grande. El parámetro UNDO_MANAGEMENT lo tengo en auto, por lo que ni me imagino como podría hacerlo.

En cualquier caso probaré lo que me dices de hacer el delete a pelo. Aunque como comenté, las pruebas que haga en el entorno de desarrollo poco tendrán que ver con las que haya ya en producción...

Un saludo
  #8 (permalink)  
Antiguo 24/02/2010, 05:39
 
Fecha de Ingreso: junio-2007
Mensajes: 891
Antigüedad: 13 años, 5 meses
Puntos: 43
Respuesta: Borrado masivo

Inmediatamente antes del delete tienes que poner esto :

SET TRANSACTION USE ROLLBACK SEGMENT XXXXXXXXX;

Donde XXXXXXXXX es obviamente el segmento de rollback que quieres utilizar :

SET TRANSACTION USE ROLLBACK SEGMENT MI_SEGMENTO_DE_ROLLBACK;

DELETE MI_TABLA;

COMMIT;
  #9 (permalink)  
Antiguo 24/02/2010, 10:38
 
Fecha de Ingreso: marzo-2005
Mensajes: 189
Antigüedad: 15 años, 8 meses
Puntos: 0
Respuesta: Borrado masivo

Vaya.

Antes he dicho que temia que me saltase el Ora-01555, pero acabo de caer en que no es ese mi problema. He confundido conceptos.
Lo que me preocupa realmentes es que genere tanto UNDO que sobrepase el límite de extensión del fichero.

El proceso se puede programar por la noche, que aunque la BD está en funcionamiento la carga de trabajo es mínima con lo que el 1555 pasa a segundo plano.
Pero he lanzado el delete a pelo en el servidor de prueba, con un tablespace UNDO de 200 Mb, y para borrar 1300000 registros no llega. He comprobado el de producción y el tablespace está limitado a 1.3 Gb. Extrapolando las conclusiones de la prueba al entorno de producción... no me llega.

Mi pregunta es:
¿si consigo hacer que funcione el arcaico script del rowcount que comenté antes, y consigo que realice un commit cada 100000 registros evito este problema?

Según mi desafinada lógica, al hacer commit la información almacenada en el UNDO es confirmada quedando plasmada en el archivo de datos y liberando los bloques de UNDO para nueva información ¿no es así? Por lo tanto cuando llegue al final del fichero comenzará a usar los del principio.

Por favor, dime que estoy en lo cierto...

Etiquetas: borrado, masivo
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 21:49.