GuilleSQL :: Microsoft SQL Server, SSIS, y más !! Votar en los Premios Bitacoras.com a Portal GuilleSQL

Como comprobar la existencia de versiones solapadas en Tablas Versionadas SCD Tipo 2 (con Fecha Desde y Fecha Hasta)

Volver a: [Trabajar con tablas versionadas (Fecha Desde y Fecha Hasta) en SQL Server, Slowly Changing Dimension (SCD) Tipo 2]


Este capítulo explica una de las tareas de comprobación que suele resultar necesaria al trabajar con tablas versionadas: comprobar la existencia de versiones solapadas en una Tabla Versionada SCD Tipo 2 (con Fecha Desde y Fecha Hasta). Esta comprobación resulta especialmente útil en entornos de Data Warehouse (DW) y Business Intelligence (BI), como medio para garantizar los datos resultantes de los procesos de carga y transformación de datos (ETL), que en ocasiones realizan intensivas transformaciones sobre las tablas versionadas (Slowly Changing Dimensions) de origen. Este capítulo explica cómo realizar esta comprobación con consultas SQL (es decir, utilizando Transact-SQL), con el ejemplo bancario de las Cuentas Corrientes y los Titulares utilizado anteriormente.

Una tarea de comprobación que puede resultar de mucha utilidad, es verificar que no existe Solapamiento de Versiones en una tabla versionada SCD Tipo 2 (con Fecha Desde y Fecha Hasta). Es decir, si tengo una tabla de Titulares, para el mismo Titular (misma Clave de Negocio o Business Key) comprobar que no existen dos Versiones válidas en un mismo momento del tiempo (no existen versiones solapadas). Claro, que lo interesante es realizar ésta comprobación SIN utilizar CURSORES.

La comprobación de versiones solapadas sobre tablas versionadas SCD Tipo 2, resulta especialmente útil en entornos de Data Warehouse (DW) y Business Intelligence (BI), principalmente porque en ocasiones los procesos de carga realizan intensivas transformaciones sobre los datos de origen (cara a su explotación en entornos de Reporting, OLAP, etc), de tal modo que estas comprobaciones de integridad ayudan a garantizar que el dato resultante de nuestras transformaciones sigue siendo un dato buendo (es decir, transformado, pero bueno ;-). En entornos operacionales, estas comprobaciones pierden importancia, ya que las propias aplicaciones (ej: COBOL/DB2/CISC, Natural/ADABAS, Infomix/4GL, etc.) suelen garantizar (por programa) la integridad de los datos.

La realización de esta comprobación es bastante sencilla. Para su explicación, vamos a continuar utilizando nuestro modelo del ejemplo bancario de las Cuentas Corrientes y los Titulares. Así, una forma de hacerlo (que no es la única) es utilizar una consulta SQL (SELECT) sobre la tabla que se desea comprobar (ej: Titulares) realizando un INNER JOIN sobre la misma tabla (ej: otra vez Titulares ;-). En la cláusula ON del INNER JOIN se debe relacionar la clave de negocio de ambas tablas (ej: TitularId).

SELECT Padre.*
FROM Titulares AS Padre
   INNER JOIN Titulares AS Hijo
      ON Padre.TitularId = Hijo.TitularId

Con esta consulta, conseguiríamos relacionar cada versión existente de la tabla Titulares (la tabla Hijo desde el punto de vista de la consulta SQL), con todas las versiones del mismo Titular (la tabla Padre) incluyendo la propia versión que se está comprobando.

Sin embargo, para cada versión, nos interesa limitar la comprobación a sólo las versiones de la tabla Padre (desde el punto de vista de la consulta SQL) que se solapan en el tiempo, es decir, que coinciden en el periodo de tiempo desde Fecha Desde (incluido) hasta Fecha Hasta (excluido). Para ello, es necesario ampliar la cláusula ON de nuestra consulta SQL para comprobar el solapamiento de los campos Fecha Desde y Fecha Hasta, como se muestra a continuación:

SELECT Padre.*
FROM Titulares AS Padre
   INNER JOIN Titulares AS Hijo
      ON Padre.TitularId = Hijo.TitularId
         AND Hijo.FecHasta > Padre.FecDesde
         AND Padre.FecHasta > Hijo.FecDesde
         AND Hijo.FecDesde < Hijo.FecHasta -- Excluir versiones del mismo día
WHERE Padre.FecDesde < Padre.FecHasta -- Excluir versiones del mismo día

Con este cambio, nuestra consulta SQL ya es capaz de devolvernos para cada versión de la tabla Hijo, todas las versiones de la tabla Padre que se solapen con ella. Sin embargo, esto no es lo que realmente queremos, ya que cada versión de la tabla Hijo, al menos se va a solapar con la misma versión de la tabla Padre (dado que son la misma tabla, es decir, ambas son la tabla Titulares en nuestro ejemplo). Para solucionar este problema, debemos utilizar un campo único (o una combinación de campos únicos) de la tabla (ej: un autonumérico, un Timestamp, etc.), que nos permita comprobar las versiones solapadas, pero excluyendo de la tabla Padre la versión que se está comprobando. Es suficiente con ampliar la cláusula ON en nuestra consulta SQL, como se muestra a continuación (para el ejemplo utilizaremos un campo ID que se supone único):

SELECT Padre.*
FROM Titulares AS Padre
   INNER JOIN Titulares AS Hijo
      ON Padre.TitularId = Hijo.TitularId
         AND Hijo.FecHasta > Padre.FecDesde
         AND Padre.FecHasta > Hijo.FecDesde
         AND Hijo.FecDesde < Hijo.FecHasta -- Excluir versiones del mismo día
         AND Padre.ID <> Hijo.ID -- Campo Unico
WHERE Padre.FecDesde < Padre.FecHasta -- Excluir versiones del mismo día

Una detalle muy importante sobre esta consulta, es que aunque estemos utilizando el operador INNER JOIN, por el tipo de comparación que estamos realizando, es como realizar un CROSS JOIN (un producto cartesiano de la tabla consigo misma) ya que estamos comparando cada fila de una tabla con cada fila de la misma tabla. Es decir, se trata de una consulta SQL bastante costosa (desde el punto de vista de rendimiento de SQL Server), por lo tanto será importante cuidar aspectos como la cobertura de índices, es decir, que la consulta pueda resolverse accediendo a índices (sin necesidad de acceder a la tabla) con el objetivo de minimizar el acceso a disco.

Una vez construida esta consulta SQL, podremos utilizarla en la forma que nos interese, ya sea tal cual se muestra en el anterior ejemplo, o de cualquier otro modo. Por ejemplo, se puede encerrar el código en Bloques TRY/CATCH, y realizar estas comprobaciones dentro del bloque TRY con sentencia IF lanzando un error RAISERROR(‘Texto error’,16,1), de tal modo que la ejecución del bloque TRY quede abortada con la ocurrencia del error, y transmitida la ejecución al Bloque CATCH, en la que se puede registrar o tratar el error producido.

Es importante, tener en cuenta que ejecutar una sentencia SQL como la anterior (tal como la vemos) a ejecutarla dentro de un IF EXISTS, nos puede cambiar el Plan de Ejecución. En las pruebas que he realizado (tanto en mi Laboratorio, como en entornos de producción de clientes), al utilizar dicha consulta SQL dentro de IF EXISTS el Plan de Ejecución utiliza operaciones NESTED LOOP, mientras que al utilizar dicha consulta SQL tal cual, el Plan de Ejecución generado utiliza operaciones HASH MATCH. La diferencia era muy clara y representativa: el Plan de Ejecución con NESTED LOOPS tardaba varios minutos para comprobar una tabla con unos pocos miles de filas, mientras que el Plan de Ejecución HASH MATCH era instantáneo al realizar la comprobación de la misma tabla. La solución, sencilla: Declarar una variable local dónde recoger el COUNT(*) de la Consulta SQL anterior, y evaluar con una sentencia IF dicha variable local para determinar si existen versiones solapada o no en nuestra tabla versionada SCD Tipo 2.

DECLARE @NumVersiones INT

SELECT @NumVersiones = COUNT(Padre.*)
FROM Titulares AS Padre
   INNER JOIN Titulares AS Hijo
      ON Padre.TitularId = Hijo.TitularId
         AND Hijo.FecHasta > Padre.FecDesde
         AND Padre.FecHasta > Hijo.FecDesde
         AND Hijo.FecDesde < Hijo.FecHasta -- Excluir versiones del mismo día
         AND Padre.ID <> Hijo.ID -- Campo Unico
WHERE Padre.FecDesde < Padre.FecHasta -- Excluir versiones del mismo día

IF @NumVersiones>0
   RAISERROR('Se han detectado Versiones Solapadas', 16, 1)

Resulta curioso como es necesario alterar la codificación de nuestro código Transact-SQL para conseguir optimizar el rendimiento de SQL Server, pues el razonamiento natural para muchos habría sido utilizar IF EXISTS en vez de una variable local, con la consecuente penalización de rendimiento.

Volver a: [Trabajar con tablas versionadas (Fecha Desde y Fecha Hasta) en SQL Server, Slowly Changing Dimension (SCD) Tipo 2]




Miembros de
Miembros de GITCA (Global IT Community Association)

Menu de Usuario
  Iniciar Sesión
  Registrarse
  Restablecer Contraseña
  Ventajas de Registrarse

Acerca de
  Contigo desde Oct 2007
  623 usuarios registrados
  86146 pageloads/mes
  Ranking Alexa 498160



Archivo

Junio de 2012 (1)
Mayo de 2012 (2)
Abril de 2012 (7)
Marzo de 2012 (16)
Febrero de 2012 (9)
Enero de 2012 (5)
Diciembre de 2011 (10)
Noviembre de 2011 (10)
Octubre de 2011 (4)
Septiembre de 2011 (5)
Agosto de 2011 (2)
Julio de 2011 (2)
Junio de 2011 (4)
Mayo de 2011 (2)
Abril de 2011 (6)
Marzo de 2011 (4)
Febrero de 2011 (10)
Enero de 2011 (5)
Diciembre de 2010 (6)
Noviembre de 2010 (4)
Octubre de 2010 (8)
Septiembre de 2010 (4)
Agosto de 2010 (1)
Julio de 2010 (3)
Mayo de 2010 (5)
Abril de 2010 (6)
Marzo de 2010 (8)
Febrero de 2010 (3)
Enero de 2010 (1)
Diciembre de 2009 (9)
Noviembre de 2009 (14)
Octubre de 2009 (2)
Septiembre de 2009 (8)
Agosto de 2009 (2)
Julio de 2009 (10)
Junio de 2009 (9)
Mayo de 2009 (10)
Abril de 2009 (9)
Marzo de 2009 (3)
Febrero de 2009 (2)
Enero de 2009 (3)
Noviembre de 2008 (2)
Octubre de 2008 (2)
Septiembre de 2008 (2)
Agosto de 2008 (5)
Julio de 2008 (5)
Junio de 2008 (1)
Mayo de 2008 (3)
Abril de 2008 (2)
Marzo de 2008 (2)
Febrero de 2008 (2)
Enero de 2008 (5)
Noviembre de 2007 (2)
Octubre de 2007 (2)






Copyright © 2007 GuilleSQL, todos los derechos reservados.