Consultar estrategias utilizando tablas temporales con versión del sistema de SQL Server 2016 para dimensiones que cambian lentamente


17

Cuando se usa una tabla temporal versionada por el sistema (nueva en SQL Server 2016), ¿cuáles son las implicaciones de la creación de consultas y el rendimiento cuando esta característica se usa para manejar Dimensiones que cambian lentamente en un gran almacén de datos relacionales?

Por ejemplo, suponga que tengo una Customerdimensión de 100.000 filas con una Postal Codecolumna y una Salestabla de hechos de miles de millones de filas con una CustomerIDcolumna de clave externa. Y suponga que quiero consultar "Total de ventas de 2014 por código postal del cliente". El DDL simplificado es así (omitiendo muchas columnas para mayor claridad):

CREATE TABLE Customer
(
    CustomerID int identity (1,1) NOT NULL PRIMARY KEY CLUSTERED, 
    PostalCode varchar(50) NOT NULL,
    SysStartTime datetime2 GENERATED ALWAYS AS ROW START NOT NULL, 
    SysEndTime datetime2 GENERATED ALWAYS AS ROW END NOT NULL,   
    PERIOD FOR SYSTEM_TIME (SysStartTime, SysEndTime) 
)
WITH (SYSTEM_VERSIONING = ON);

CREATE TABLE Sale
(
    SaleId int identity(1,1) NOT NULL PRIMARY KEY CLUSTERED,
    SaleDateTime datetime2 NOT NULL,
    CustomerId int NOT NULL FOREIGN KEY REFERENCES Customer(CustomerID),
    SaleAmount decimal(10,2) NOT NULL
);

Lo que resulta interesante es que los clientes pueden haberse mudado durante el año, por lo que el mismo cliente puede tener diferentes códigos postales. ¡Y es incluso remotamente posible que un cliente se haya alejado y luego haya regresado, lo que significa que podría haber múltiples registros históricos para el mismo cliente con el mismo código postal! Mi consulta de "ventas por código postal" debería poder calcular los resultados correctos independientemente de cómo cambien los códigos postales de los clientes con el tiempo.

Entiendo cómo usar tablas temporales para consultar solo la dimensión del cliente (por ejemplo SELECT * FROM Customer FOR SYSTEM_TIME FROM '2014-1-1' TO '2015-1-1'), pero no estoy seguro de cómo unirme de manera más precisa y eficiente a la tabla de hechos.

¿Es así como debería consultarlo?

SELECT c.PostalCode, sum(s.SaleAmount) SaleAmount
FROM Customer c FOR SYSTEM_TIME FROM '2014-1-1' TO '2015-1-1'
    JOIN Sale s ON s.CustomerId = c.CustomerId
WHERE s.SaleDateTime >= '2014-1-1' AND s.SaleDateTime < '2015-1-1'
    AND c.SysStartTime >= s.SaleDateTime
    AND c.SysEndTime < s.SaleDateTime
GROUP BY c.PostalCode

¿Y cuáles son las consideraciones de rendimiento que debo tener en cuenta al hacer consultas como esta?

Respuestas:


1

Creo que, en su caso, es necesaria una tabla derivada para aislar el número de consultas de mutaciones de códigos postales por cliente:

SELECT c.postalcode 
, sum(s.SaleAmount) SaleAmount
, count(postcode_mutations.customerid) as CntCustomerChangedPostCode   
FROM dbo.Sale s
JOIN dbo.Customer c on s.customerid = c.customerid

LEFT JOIN (
SELECT 
    CustomerID
FROM [dbo].[Customer]
FOR SYSTEM_TIME FROM '20140101' TO '20150101'
GROUP BY CustomerID
HAVING COUNT(DISTINCT PostalCode) > 1
) postcode_mutations on s.customerid = postcode_mutations.customerid

WHERE s.SaleDateTime >= '2014-1-1' AND s.SaleDateTime < '2015-1-1'
GROUP BY c.PostalCode

upd: dado que se supone que la consulta debe servir escenarios DWH / Analytics, la indexación del almacén de columnas es una opción para verificar. También hice algunos puntos de referencia anteriormente para una tabla de 10 millones de filas.


¿Por qué es necesario contar la cantidad de cambios por cliente? Los clientes que cambian el código postal durante el año agregan complejidad a la consulta, pero en realidad no parece ser necesario informar sobre esos cambios.
Justin Grant

@JustinGrant El número de cambios es para mostrar cómo se pueden recuperar estas mutaciones de los datos históricos. Sin embargo, agregó estas líneas ayer: mi consulta de "ventas por código postal" debería poder calcular resultados correctos independientemente de cómo cambien los códigos postales de los clientes con el tiempo. Haga la solicitud más clara. En ese caso, SYSTEM_TIME debe establecerse de la misma manera para ambas tablas. y hay dos formas: 1) Usar tablas privadas y aplicar system_time para ambas tablas. 2) O simplemente cree una vista que contenga una unión y aplique SYSTEM_TIME al consultar la vista
Alexandr Volok
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.