lunes, 10 de septiembre de 2007

Limpiando código DDL

A propósito de Un extractor de DDL en archivos separados, me preguntaron como evitaba exportar las cláusulas de storage en Oracle 9i, únicamente dejando las que especifican los tablespaces.

SQL> create table t (a int);

Tabla creada.

SQL> select dbms_metadata.get_ddl('TABLE','T') from dual;

DBMS_METADATA.GET_DDL('TABLE','T')
--------------------------------------------------------------------------------

CREATE TABLE "LFERNANDEZ"."T"
( "A" NUMBER(*,0)
) PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING
STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
TABLESPACE "USERS"


En la práctica, las cláusulas PCTFREE, PCTUSED, STORAGE, etc, no son útiles durante el desarrollo, sino cuando los objetos son puestos en producción. Es allí donde el detalle en la especificación de storage de los objetos tiene un impacto significativo sobre la performance de los sistemas.

Repasando las opciones disponibles en el paquete dbms_metadata y en particular la función set_transform_param, encontramos que podemos generar el código de asignación de tablespace pasando el valor 'TABLESPACE' como segundo parámetro y TRUE como tercero:
dbms_metadata.set_transform_param(dbms_metadata.session_transform, 'TABLESPACE', TRUE);

Desafortunadamente, esta opción es ignorada cuando deshabilitamos todo el STORAGE usando:
dbms_metadata.set_transform_param(dbms_metadata.session_transform, 'STORAGE', FALSE);

No tenemos alternativa entre: o generar todo el storage, o no generarlo en absoluto.

El camino que termina siendo elegido es el de generar todo el código DDL y luego procesar el archivo de salida con algun lenguaje con buenas cualidades para procesamiento de texto, como por ejemplo Perl o AWK.

No se requiere ser experto en AWK para programar un sencillo script que elimine algunas líneas de archivos:

BEGIN {flag=2}
/^ *) PCTFREE/{print ")"; flag=0}
/^ *PCTFREE/{flag=0}
flag==0 && $0~/)$/{flag=1}
flag==2
flag==1{flag=2}


Esta es la idea: uso flags para saber cuándo imprimir y cuándo no, luego tengo dos posibles comienzos con PCTFREE, el primero para tablas comunes y el segundo para el caso de tablas particionadas (las cuales no son antecedidas por un paréntesis).

Cualquier comentario para mejorar la performance de este script será bienvenido!

Ver también
Un extractor de DDL en archivos separados

No hay comentarios: