Sunday, March 22, 2009

Extracción de datos con marca de tiempo (Timestamp Data Extraction) con SSIS

Hola a todos.
Tal vez hayas oído hablar de los diferentes métodos de extracción de datos que existen en el mundo ETL: Timestamp, fecha de modificación, bits de columna, Checksum, Triggers, o incluso con SQL Server 2008 tenemos Change Data Capture o la instrucción MERGE.
Hoy voy a explicar una solución para Timestamp y la manera de aplicarlo con SSIS. En primer lugar tenemos que entender qué tipo de datos es Timestamp y cómo usarlo.
El tipo de datos Timestamp se compone de un conjunto de bytes que nos ayuda a identificar las filas que se han modificado. Cuando se agrega una columna TIMESTAMP en una tabla (sólo se permite una por tabla), cada fila insertada o actualizada se marca con un nuevo valor incremental de Timestamp. Sin embargo, se debe tener en cuenta que no es posible convertir un valor de Timestamp a algo parecido a una fecha, como mucha gente piensa. Es sólo una secuencia de bytes, un número hexadecimal que crece constantemente.

Lo primero es tener una tabla de control para guardar el último Timestamp procesado en cada ejecución de nuestro proceso de ETL. De esta manera, buscaremos en cada ejecución sólo las filas que se han modificado desde la última vez que ejecutamos.

Vamos a ver cómo hacerlo con un ejemplo.
Tendremos una tabla de clientes de origen, en la que hemos añadido una columna timestamp. También tendremos una tabla de clientes de destino y una tabla de control para almacenar el último Timestmap leído de la tabla de origen. Las tablas deberían tener este aspecto:

Ahora vamos a diseñar el paquete SSIS. Con el fin de no perder ninguna fila, debemos recuperar los timestamps al principio, y almacenarlos en dos variables de SSIS. De esta forma definimos el intervalo de filas que vamos a leer durante la ejecución del paquete, y no importará si mientras corre el paquete se modifican más filas. Las dos SELECTs son las siguientes:
• La primera recupera el timestamp de la última ejecución, almacenado en la tabla de control. Almacenaremos el valor del resultado en la variable de SSIS TimestampTo.


SELECT LastReadTimestamp FROM LastReadTimestamps WHERE TableName = 'customers'


• La segunda SELECT recupera el valor máximo de todos los timestamp de la tabla de clientes de origen. El valor lo guardamos igualmente en una variable de SSIS llamada TimestampFrom.


SELECT convert(varchar(20),convert(numeric(20,0),max(timestamp) + 0)) AS timestamp FROM dbo.Customers


En el siguiente paso de flujo de control diseñaremos el flujo de datos. Con una tarea de 'Data Flow Task' moveremos las filas modificadas desde la fuente a la tabla de destino. Para ello, utilizaremos las dos variables como parámetros en el componente 'OLEDB Source Component'. La sentencia SELECT debería tener este aspecto:


SELECT CustomerID,Name,Surname,Location
FROM Customers
WHERE convert(numeric(20,0),timestamp + 0) > ? AND convert(numeric(20,0),timestamp + 0) <= ?



Tenemos que convertir el timestamp a un valor numérico para compararlo con el parámetro. SQL Server no es capaz de convertir directamente de timestamp a un numérico, pero poniendo un "+0" después del nombre de la columna se resuelve el problema rápidamente.

Una vez tenemos los valores modificados que puede sincronizar fácilmente la tabla de destino, por ejemplo con un componente SCD. El diseño del flujo de datos debería tener este aspecto:

Finalmente, nos quedaría almacenar el timestamp del último cliente leído en la ejecución, que es exactamente el valor almacenado en la variable TimestampTo. Guardaremos el valor mediante una tarea de tipo "Execute SQL Task" con un parámetro:


UPDATE LastReadTimestamps
SET LastReadTimestamp = convert(numeric(20,0), ?)
WHERE TableName = 'Customers'



Con este enfoque se puede mejorar fácilmente el rendimiento de nuestro flujo de datos de SSIS debido a que sólo se procesan las filas que se han modificado desde la última ejecución. No hay ningún tipo de trabajo extra, todas las filas que se procesan sabemos con certeza que han sido modificadas de una u otra forma.

Espero que hayan encontrado interesante este artículo.