使用SQL Server 2016系统版本的时态表进行慢速变化维度的查询策略


17

当使用系统版本的时态表(SQL Server 2016中的新增功能)时,当此功能用于处理大型关系数据仓库中的维缓慢变化时,查询创作和性能含义是什么?

例如,假设我有一个Customer带有Postal Code列的100,000行维,一个Sales带有CustomerID外键列的数十亿行事实表。并假设我要查询“按客户的邮政编码进行的2014年销售总额”。简化的DDL就是这样(为了清楚起见,省略了许多列):

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
);

有趣的是,客户可能在这一年内搬家,因此同一位客户的邮政编码可能不同。甚至有可能某个客户离家再搬回,这意味着同一位客户使用相同的邮政编码可能会有多个历史记录!我对“按邮政编码销售”的查询应该能够计算出正确的结果,而不管客户的邮政编码随时间如何变化。

我了解如何使用时态表单独查询客户维度(例如SELECT * FROM Customer FOR SYSTEM_TIME FROM '2014-1-1' TO '2015-1-1'),但是我不确定如何最准确,最有效地加入事实表。

这是我应该如何查询吗?

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

在进行这样的查询时,应该注意哪些性能方面的考虑?

Answers:


1

我认为,在您的情况下,必须使用派生表来隔离每个客户的邮政编码突变查询数量:

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:由于查询应用于DWH / Analytics方案,因此列存储索引是一种检查选项。之前,我还为1000万行表制定了一些基准测试


为什么有必要计算每个客户的更改数量?在这一年中更改邮政编码的客户确实增加了查询的复杂性,但实际上并不需要报告这些更改。
贾斯汀·格兰特

@JustinGrant更改数量是为了显示如何从历史数据中检索这些突变。但是,这些行是您昨天添加的:无论客户的邮政编码随时间如何变化,我对“按邮政编码销售”的查询都应该能够计算出正确的结果。使请求更清晰。在这种情况下,应该为两个表设置相同的SYSTEM_TIME。有两种方法:1)使用私有表并对两个表应用system_time。2)或简单地创建一个持有
联接
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.