sábado, enero 21, 2012

Rotación de Tablas

Hola a todos.

Después de pensar mucho sobre un post que fuera de utilidad, pagándole un regalo de cumpleaños a mi amigüita Sorey, y además de tener un ratico en el almuerzo, les quiero compartir la siguiente experiencia que tuve hace unos años cuando trabajaba para una empresa que me dejó muy malos recuerdos (pero esa es otra historia :-) ).

Sucede que trabajando para un proyecto de telcos, tenía(mos) que monitorear un conjunto de tablas INMENSAS, tanto en metadata, la que menos tenía, tenía 60 columnas, siendo varchar2(64) el común denominador, como en registros (diariamente bajita la mano, eran 9 millones de registros y al final de mes, ya pueden hacer cálculos...).

Uno de los requisitos sobre los que se hizo mucho hincapié fue el almacenamiento de los datos de los últimos 6 meses (por ley para telcos en ese entonces).

El siguiente requisito, origen de este post, era que el respaldo de dicha información no podría demorar más de un segundo (!!!), lo cual tiene sentido, dado el carácter de alta disponibilidad del sistema.

Después de mucho trastabillar con el conocido "Insert Into Historico Select * From Tbl; Truncate Table Tbl;" y viendo que, cuando nos iba bien, se demoraba 1 hora el cambio de mes, se me ocurrió una idea interesante a la que llamé "Rotación de Tablas" (y si alguién ya la había implementado, me disculpa, pero citando a topogigio "lo dije yo primero" ).

El razonamiento inicial fue intentar mover los datos entre tablas, lo cual cumplía el primer requisito, pero no el segundo; asi que en vez de moverlos, más bien se recalculaban sus identificadores y voilá, una operación lógica en vez de una física: "caching!" .

Aprovechando las características de las tablas que tenía en ese entonces, redireccionar su metadata fue fácil, y eso logró cumplir con el segundo requisito.

No voy a publicar código debido a que tengo poco tiempo, más bien voy a dar los lineamientos generales que aplican para cualquier motor de base de datos. Asi pués que, entrando en materia:

Precondiciones de las tablas a rotar

  • Nombre de los constraints (pk, uk, fk, defaults, checks) predecibles o ninguno (preferible).
  • Nombre de los índices también predecibles.
  • Nombre de los autoincrementos (si hay, secuencias, identity, etc) también predecibles.
  • Cero Triggers (muy importante: facilitan el trabajo)
  • Cero claves foráneas (muy importante, mejor si sólo son tablas de vaciado de datos)

Precondiciones del motor de base de datos:

  • Soporte para manipulación de metadatos (renombrar tablas, columnas, constraints, índices, autoincrementos, etc).
  • Soporte para bloqueo de metadatos y restricción de conexiones temporalmente.

Ahora si, cumpliendo las precondiciones, se puede delinear la transacción de la siguiente forma lógica:

  1. Bloquear acceso a las tablas y su metadata solo a la operación entrante.
  2. Deshabilitar los constraints como índices, checks, y claves foráneas (se puede hacer a través de un procedimiento que analice el INFORMATION_SCHEMA).
  3. Renombrar la(s) tabla(s) (por ejm: TablaDatos -> TablaDatosHist201102)
  4. Renombrar los constraints referenciando el nombre nuevo de la tabla.
  5. Crear una tabla nueva idéntica en metadata. (por ejm: Create Table TablaDatos As TablaDatosHist201102, o mejor tener una tabla plantilla)
  6. Crear los constraints para la nueva tabla con los nombres originales.
  7. Re-habilitar los constraints deshabilitados.
  8. Liberar el acceso.

Dependiendo del motor de base de datos que estemos usando, es probable que otras consideraciones técnicas deban tenerse en cuenta, como por ejemplo, reindexar, re-calcular estadísticas en la tabla vieja, recuperar espacio físico, pero eso puede hacerse de forma asíncrona una vez ya esté en sitio la nueva tabla vacía y el sistema en línea.

Con este método se logró solucionar el problema cambio de mes en un segundo en el dichoso sistema ese.

Saludos, hasta otra oportunidad.

1 comentario:

Anónimo dijo...

Muy interesante.