Recarga incremental particionada – Parte I

En este artículo voy explicar cómo realizar una carga incremental peródica (habitualmente diaria) y proveer el código para realizar cargas incrementales particionadas por cualquier campo numérico.

Básicamente una carga incremental funciona del siguiente modo:

incrementalLoad

 

Es decir que por primera vez realizamos una carga completa y luego cada día solo tomamos las novedades del día anterior y a estas novedades le agregamos todo lo que ya estaba almacenado en el QVD y que NO está en dichas novedades.

A modo de ejemplo si el día X el cliente (ID=99)  se da de alta y declara como dirección “Ruta 66 Km 456” ese día se va a detectar esta fila como una novedad, debido a que no existe en el QVD, y se va a agregar a dicho QVD. Posteriormente el día X+N el cliente se muda a “Ruta 2 Km 38” y el proceso de recarga incremental va a detectar la novedad y la va a agregar al resto del archivo QVD (otros clientes) DESCARTANDO por completo de este archivo lo que había guardado para el cliente 99 (Ruta 66 Km 456) y en su lugar guardando los datos del cliente 99 que se recuperaron de la BD.

Para hacer esto se requiere que la tabla sobre la cual se va a hacer la recarga incremental cumpla con 2 características:

1-      Debe tener un identificador único.

2-      Debe tener un campo de tipo fecha o fecha-hora donde cada vez que un registro es creado y/o modificado en CUALQUIER modo por el sistema origen (transaccional) este campo se actualice con la fecha hora del momento. Esta tarea es un compromiso que debe pactarse con los responsables del sistema origen.

Para concretar lo explicado y seguir avanzando aquí va el código de una recarga incremental básica:

Set TimestampFormat=’YYYY-MM-DD hh:mm:ss[.fff]’; //Spanish format

LET v_CompareDate_1 = DATE(TODAY()-1,’YYYY-MM-DD’); // Yesterday

//Checks if the QVD file exists for the first time
IF NOT ISNULL(QvdCreateTime(‘incrementalTable.QVD’)) THEN
//It is not the first time, because the QVD file exists

//Recove all the news (new records + updates since last load (v_CompareDate_2)

incrementalTable:
LOAD *; //If prefer can detail a list of fields
SQL SELECT *  //Can detail fields list
FROM sourceTable
WHERE LastUpdateDate >= TO_DATE(‘$(v_CompareDate_2)’,’YYYY-MM-DD’);

//Adds records stored en prvious days into QVD file and doesn’t exist as news
CONCATENATE (incrementalTable)
LOAD *
FROM incrementalTable.QVD (QVD)
WHERE NOT EXISTS (UNIQUEID);

ELSE
// first time running: the QVD file doesn’t exist

// So it makes a full load

incrementalTable:
LOAD *;
SQL SELECT * FROM sourceTable;

END IF

STORE incrementalTable incrementalTable.QVD;
DROP TABLE incrementalTable;

LET v_CompareDate_2 = ‘$(v_CompareDate_1)’;
 

 Vamos a destacar algunos puntos del código:

1)      ¿Cómo detectamos las novedades?

Lo hacemos leyendo de la BD todo lo que sucedió después de la última vez que corrió este mismo script: “WHERE LastUpdateDate >= TO_DATE(‘$(v_CompareDate_2)’,’YYYY-MM-DD’)”. Esto podría ser ayer o hace dos semanas, no importa porque la fecha de la última corrida (menos un día) quedó almacenada en la variable v_CompareDate_2 (recordar que las variables de QV son persistentes en el tiempo).

2)      ¿Cómo evitamos cargar novedades de filas que ya habían sido cargadas previamente?

Si en el QVD hubiera filas almacenadas ya presentes entre las novedades nos quedaremos con las novedades y DESCARTAMOS lo que estaba guardado: “WHERE NOT EXISTS (UNIQUEID)”

3)      ¿Cómo juntamos las novedades con el resto de los datos previamente almacenados?

Concatenando ambos conjuntos: “CONCATENATE (incrementalTable)”

4)  ¿Cómo “preparamos” el script para la próxima ejecución? Setando la fecha v_CompareDate_2 al valor de v_CompareDate_1: “LET v_CompareDate_2 = ‘$(v_CompareDate_1)’”

De este modo tenemos listo un script capaz de cargar la totalidad de una tabla en su primera ejecución y luego solo extraer y almacenar las novedades sustituyendo las viejas versiones de esos registros si existieran.

No obstante esta técnica qunque optimiza la lectura de la BD y la transferencia de datos desde esta tiene un problema de performance en caso que el QVD resultante sea verdaderamente grande (>1 ó 2 TByte) y es que cada vez que corre este script tal y como está primero lee y luego graba un archivo muy grande al disco, lo que incluso con servidores medianamente potentes puede estar en el orden de los 10-20 minutos, haciendo muy pesada la ejecución, consumiendo valioso tiempo de una ventana operativa que en muchas organizaciones suele estrecharse a unas pocas horas de madrugada.

En la segunda parte de esta nota voy a explicar cómo modificar y empaquetar este código para leer y grabar solo pequeñas porciones del QVD (en realidad muchos pequeños QVDs), optimizando los tiempos y el recurso de acceso a disco.

Acerca de pparnisari
Casi 44 vueltas al sol. Licenciado en sistemas. Curioso, investigador, excelente para resolver problemas prácticos. Casado, 2 hijos, cada vez con mas preguntas y respuestas mas en duda. Almost 44 laps to the sun. System engineer. Curious, researcher, great for solving practical problems. Married, 2 children, each time with more questions and more answers in doubt.

Deja un comentario

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: