13 octubre 2009

Manejando hechos que (aún) no tenemos su dimensión (early arriving facts) en SSIS

Probablemente esto les ha pasado antes o les puede pasar cuando creen sus paquetes de Integration Services para cargar sus tabla de facts: tienen que procesar unos hechos (facts) que han llegado antes de que la dimensión (o mejor dicho el miembro) que generó el hecho exista en su tabla dimensión. Por ejemplo, tienen una factura para un cliente que por algún motivo no ha sido ingresado (aún) a su dimensión de Productos.

Básicamente hay 2 opciones para manejar estos “early arriving facts”. La primera es (tal como lo hace Project REAL), implementar un Script Component que inserte el valor que no se encuentre en la dimensión (que no haga “match”) y que lo integre al “cache” del Lookup Component original usando código de .NET. La siguiente extraída de la documentación del proyecto (Project REAL ETL Design Practices), muestra el diseño de esta estrategia:

clip_image002

 

La segunda forma (que llamó mi atención por ser más simple y efectiva), es la de usar un segundo Lookup Component para los valores que no se encuentren en el primero, llamando a un Stored Procedure para que haga el trabajo y lo inserte al cache de este segundo Lookup (configurando para que se ejecute con Partial Cache). Todo este detalle lo encuentran en este excelente post del Customer Advisory Team (CAT) de SQL (en inglés). Aquí algunas imágenes de ese artículo:

clip_image002_2 

clip_image004_thumb

 clip_image006_2

CREATE PROCEDURE Generate_SK_A
  @NK_A CHAR(10) /* The key to find a surrogate for */
AS
SET NOCOUNT ON

/* Prevent race conditions */
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE

/* Check if we already have the key (procedure is idempotent) */
DECLARE @SK_A INT
SELECT @SK_A = SK_A
FROM Dim_A
WHERE NK_A = @NK_A

/* The natural key was not found, generate a new one */
IF @SK_A IS NULL BEGIN
INSERT Dim_A (NK_A) VALUES (@NK_A)
SET @SK_A = SCOPE_IDENTITY()
END

/* Return the result. 
  IMPORTANT: must return same format is the SELECT statement we replaced */
SELECT @SK_A AS SK_A, @NK_A AS NK_A

Ambas opciones son muy buenas para solucionar nuestro problema con los “early arriving facts”, cuál escogen?

Alan