jueves, 5 de noviembre de 2009

Como particionar una tabla en linea?

Supongamos que tenemos una tabla, esta puede estar o no particionada y la idea en este caso puntual es volver a particionarla por mes con creación de particiones en forma automática. Para esta tarea vamos a utilizar el pakage DBMS_REDEFINITION.

paso 1.

El primer paso es chequear si la tabla se puede redefinir online, si la salida del script mostrado debajo no da ningún error, entonces podemos hacer uso del packages DBMS_REDEFINITION.

DECLARE
ndummy NUMBER;
begin
DBMS_REDEFINITION.CAN_REDEF_TABLE('SCHEMA','TABLA_ORIGINAL');
EXCEPTION
WHEN OTHERS THENRAISE;
end;
/

Paso 2.

Creamos la tabla temporal con la nueva estructura, en mi caso sólo la particioné por otro campó y ademas lo hice por mes utilizando la clausula "INTERVAL( NUMTOYMINTERVAL(1,'MONTH'))" provista en 11g la cual hace que las partiones se creen en forma automática.

NOTA:
- Para no generar archive's cambiar a modo NOLOGGING tanto la definición de la tabla como el clob.
- Crear las particiones necesarias para alojar la tabla completa.
- Hay que asegurarnos de tener espacio en el tablespace, mínimo el tamaño de la tabla original y un poco más.
- Debe tener la misma PK que la Original.
- En este punto no se debe crear ningún indice ni constraint ni trigger que no sea la PK.
- La tabla debe ser creada con los cambios deseados. - La tabla temporal debe ser creada con esos cambios.

--prompt creo la tabla temporal

CREATE TABLE SCHEMA.DOCUMENTOS_TEMP
(
IDNS_DOCUMENTO NUMBER NOT NULL,
SD_ANIO NUMBER(4) NOT NULL,
SD_ADUANA VARCHAR2(3 CHAR) NOT NULL,
SD_DOCUMENTOTIPO VARCHAR2(4 CHAR) NOT NULL,
SD_DOCUMENTONRO VARCHAR2(6 CHAR) NOT NULL,
SD_LETRA VARCHAR2(1 CHAR) NOT NULL,
SG_DOCUMENTO BLOB NOT NULL,
SD_CAJA VARCHAR2(6 CHAR) NOT NULL,
NS_DESPACHANTE NUMBER NOT NULL,
SD_CUITDESPACHANTE VARCHAR2(11 CHAR) NOT NULL,
SD_DESPACHANTE VARCHAR2(100 CHAR) NOT NULL,
NS_IMPORTADOREXPORTADOR NUMBER NOT NULL,
SD_CUITIMPORTADOREXPORTADOR VARCHAR2(11 CHAR) NOT NULL,
SD_IMPORTADOREXPORTADOR VARCHAR2(100 CHAR) NOT NULL,
H_ALTA DATE DEFAULT SYSDATE NOT NULL,
NC_PAGINAS NUMBER(4) NOT NULL,
NC_PAGINASLOTE NUMBER(4),
NC_BYTESPDF NUMBER,
H_UPD DATE
)
TABLESPACE DATA_CLOB
NOLOGGING
PARTITION BY RANGE (H_ALTA)
INTERVAL( NUMTOYMINTERVAL(1,'MONTH'))
(
PARTITION VALUES LESS THAN (TO_DATE(' 2009-09-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN'))
NOLOGGING
NOCOMPRESS
TABLESPACE DATA_CLOB
LOB (SG_DOCUMENTO) STORE AS
( TABLESPACE DATA_CLOB
ENABLE STORAGE IN ROW
CHUNK 8192
RETENTION
NOCACHE
NOLOGGING
),
PARTITION VALUES LESS THAN (TO_DATE(' 2009-10-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN'))
NOLOGGING
NOCOMPRESS
TABLESPACE DATA_CLOB
LOB (SG_DOCUMENTO) STORE AS
( TABLESPACE DATA_CLOB
ENABLE STORAGE IN ROW
CHUNK 8192
RETENTION
NOCACHE
NOLOGGING
),
PARTITION VALUES LESS THAN (TO_DATE(' 2009-11-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN'))
NOLOGGING
NOCOMPRESS
TABLESPACE DATA_CLOB
LOB (SG_DOCUMENTO) STORE AS
( TABLESPACE DATA_CLOB
ENABLE STORAGE IN ROW
CHUNK 8192
RETENTION
NOCACHE
NOLOGGING
),
PARTITION VALUES LESS THAN (TO_DATE(' 2009-12-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN'))
NOLOGGING
NOCOMPRESS
TABLESPACE DATA_CLOB
LOB (SG_DOCUMENTO) STORE AS
( TABLESPACE DATA_CLOB
ENABLE STORAGE IN ROW
CHUNK 8192
RETENTION
NOCACHE
NOLOGGING
)
)
NOCOMPRESS
NOCACHE
NOPARALLEL
MONITORING;


Paso3.

Asociamos la tabla temporal con la tabla a redefinir.

prompt Iniciar el proceso de redefinición
BEGIN
DBMS_REDEFINITION.START_REDEF_TABLE ('SCHEMA','DOCUMENTOS','DOCUMENTOS_TEMP',
'IDNS_DOCUMENTO IDNS_DOCUMENTO,
SD_ANIO SD_ANIO,
SD_ADUANA SD_ADUANA,
SD_DOCUMENTOTIPO SD_DOCUMENTOTIPO,
SD_DOCUMENTONRO SD_DOCUMENTONRO,
SD_LETRA SD_LETRA, SG_DOCUMENTO
SG_DOCUMENTO, SD_CAJA SD_CAJA,
NS_DESPACHANTE NS_DESPACHANTE,
SD_CUITDESPACHANTE SD_CUITDESPACHANTE,
SD_DESPACHANTE SD_DESPACHANTE,
NS_IMPORTADOREXPORTADOR NS_IMPORTADOREXPORTADOR, SD_CUITIMPORTADOREXPORTADOR SD_CUITIMPORTADOREXPORTADOR, SD_IMPORTADOREXPORTADOR SD_IMPORTADOREXPORTADOR,
H_ALTA H_ALTA,
NC_PAGINAS NC_PAGINAS,
NC_PAGINASLOTE NC_PAGINASLOTE,
NC_BYTESPDF NC_BYTESPDF,
H_UPD H_UPD',
dbms_redefinition.cons_use_pk);
END;
/

Paso4.

Copia las dependencias de la tabla original a la tabla temporal.

prompt Copiar el objeto dependiente

DECLARE
num_errors PLS_INTEGER;
BEGIN
DBMS_REDEFINITION.COPY_TABLE_DEPENDENTS('SCHEMA', 'DOCUMENTOS','DOCUMENTOS_TEMP', DBMS_REDEFINITION.CONS_ORIG_PARAMS, TRUE, TRUE, TRUE, TRUE, num_errors);
END;
/


Paso5.

Hacemos un chequeo de errores.
prompt Consultar la vista DBA_REDEFINITION_ERRORS para saber si hubo algún error.

select object_name, base_table_name, ddl_txt from DBA_REDEFINITION_ERRORS;
Paso6.
Mantenemos sincronizada la tabla temporal con los datos de la tabla original.

prompt Sincronizar la tabla temporal o intermedia

BEGIN
DBMS_REDEFINITION.SYNC_INTERIM_TABLE('SRD', 'DOCUMENTOS','DOCUMENTOS_TEMP');
END;
/


Paso7.

Registra la dependendia de objetos ( indices, trigger o constraint ) y finaliza la redefinición.

prompt Completar la redefinicion

BEGIN
DBMS_REDEFINITION.FINISH_REDEF_TABLE('SRD', 'DOCUMENTOS','DOCUMENTOS_TEMP');
END;
/

Paso8.

Volver a poner en modo LOGGING a la tabla.

alter table SCHEMA.DOCUMENTOS LOGGING ;
alter table SCHEMA.DOCUMENTOS MODIFY LOB (SG_DOCUMENTO) (CACHE LOGGING);

NOTA:

En caso de dar error y querer realizar rollback de la operacion se puede ejecutar lo siguente

BEGIN dbms_redefinition.abort_redef_table('SRD', 'DOCUMENTOS','DOCUMENTOS_TEMP');
END;
/