miércoles, 14 de mayo de 2008

Re: Pregunta de Oracle (email!)

El día 14 de mayo de 2008 11:25, Federico <fede@mail.com> escribió:
Hola Martín, cómo estás? Me surgió una duda sobre Oracle y se me ocurrió molestarte a vos...de todos modos no es mucho.

Tengo una tabla de unos 9 millones de registros (que no está particionada en table spaces), y cuando quiero borrar una cantidad importante de registros el SQL Plus se queda colgado, supongo que en algún momento da un timeout y luego se pone a hacer el rollback del que me contabas el otro día. Te parece que hacer un delete con un rownum pueda funcionar? o puedo llegar a romper algo?

mil gracias,

un abrazo,

Fede




El día 14 de mayo de 2008 23:16, Martin <martin@mail.com> escribió:


Romper no... a lo sumo va a seguir sin responder.

Pueden ocurrir muchas cosas... Se me ocurren otras alternativas pero no te sabria decir cual es la que te conviene mas...

¿Cuantos registros de los 9 millones tenes que borrar? ¿Son muchos mas que los que dejas? ¿Los borras con algun criterio o estas borrando los primeros N millones (la alternativa donde te serviria el ROWNUM)?

Al ser millones de reg la cosa se pone mas complicada...

Puede que esten mal dimensionados los parametros de la base, que los redo o el undo sean chicos para una transaccion tan grande (Oracle se asegura grabando en los redo y undo logs que de caerse la base pueda mantener la atomicidad del DELETE)...

Si la tabla estuviera particionada podrias truncar una particion (una particion no un tablespace, una tabla siempre esta contenida dentro de un unico tablespace). Aunque tendrias que tener cuidado que no tenga indices globales que se invaliden, si los hubiera tenes que hacer el truncate de la particion con la opcion rebuild online...

Ahora la pregunta es tienen pensado particionarla? ¿Pueden particionarla y despues hacer el truncate de la particion? (para particionarla hay que recrear el objeto).

Si no fueran muchos registros te conviene hacer un pequeño PL-SQL que haga commits cada cierta cantidad de registros (ojo porque le estas quitando atomicidad a la operacion y deja de hacerse o deshacerse por completo, solo x bloque PL que definas)...

Podes usar una tabla temporal en modo nologging asi no te caga llenando redo y undo y mandar los registros que queres conservar a la temporal y dropear la original para despues renombrar la temporal a la original... vas a tener que hacer otras cosas en medio como deshabilitar constraints si los hubiera... fijarte que el "manoseo" no haga que te exploten los tablespaces por el espacio que va a ocupar la tabla temporal (si no es un gran porcentaje el que borras pensa que seria como duplicar la tabla)...

No se si escuchaste de una instruccion BULK INSERT (o BULK COLLECT) que son para cargas masivas de datos, tenes una similar para borrar masivamente (que jamás la usé pero imagino que te puede ser de suma utilidad) que se llama...

chan ... chan... jajajaja. BULK DELETE como a esta altura ya te imaginaras por analogia con el anterior.

Aca va un ejemplo que encontre en la WEB:

DECLARE
TYPE num_nt IS TABLE OF VARCHAR2(20);
TYPE descr_nt IS TABLE OF VARCHAR2(20);

nt_x_nums num_nt := num_nt();
nt_a_descrs descr_nt := descr_nt();

v_cnt_sqlrow NUMBER := 0;
SELECT id BULK COLLECT
INTO nt_x_nums
FROM a;

v_cnt_sqlrow :=SQL%ROWCOUNT;
-- DBMS_OUTPUT.PUT_LINE(v_cnt_sqlrow);

FORALL i IN nt_x_nums.FIRST..nt_x_nums.LAST
DELETE FROM t
WHERE id= nt_x_nums(i)

RETURNING id BULK COLLECT INTO nt_a_descrs
Espero que te haya servido!

Cualquier cosa preguntame!

Slds,

Martin

PD: Aca va el link de la pagina de donde saqué el ejemplo.

http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:5033906925164.


No hay comentarios: