我在OLTP中有以下表查找表
CREATE TABLE TransactionState
(
TransactionStateId INT IDENTITY (1, 1) NOT NULL,
TransactionStateName VarChar (100)
)
当这进入我的OLAP时,我按如下方式更改结构:
CREATE TABLE TransactionState
(
TransactionStateId INT NOT NULL, /* not an IDENTITY column in OLAP */
TransactionStateName VarChar (100) NOT NULL,
StartDateTime DateTime NOT NULL,
EndDateTime NULL
)
我的问题是关于TransactionStateId列。随着时间的推移,我的OLAP中可能有重复的TransactionStateId值,但是使用StartDateTime和EndDateTime的组合,它们将是唯一的。
我见过Type-2 Dimensions的样本,其中添加了OriginalTransactionStateId并且传入的TransactionStateId被映射到它,加上一个新的TransactionStateId IDENTITY字段成为PK并用于连接。
CREATE TABLE TransactionState
(
TransactionStateId INT IDENTITY (1, 1) NOT NULL,
OriginalTransactionStateId INT NOT NULL, /* not an IDENTITY column in OLAP */
TransactionStateName VarChar (100) NOT NULL,
StartDateTime DateTime NOT NULL,
EndDateTime NULL
)
我应该使用bachellorete#2还是bachellorete#3?
答案 0 :(得分:2)
通过这句话:
结合
StartDateTime
和EndDateTime
,它们将是唯一的。
你的意思是他们从不重叠或者他们满足数据库UNIQUE
约束?
如果是前者,那么您可以在联接中使用StartDateTime
,但请注意它可能效率低,因为它会使用"<="
条件而不是"="
。
如果是后者,则只使用假身份。
数据库通常不允许为此查询提供有效的算法:
SELECT *
FROM TransactionState
WHERE @value BETWEEN StartDateTime AND EndDateTime
,除非你使用SPATIAL
数据进行了晦涩的技巧。
这就是为什么你必须在JOIN
:
SELECT *
FROM factTable
CROSS APPLY
(
SELECT TOP 1 *
FROM TransactionState
WHERE StartDateTime <= factDateTime
ORDER BY
StartDateTime DESC
)
,这将剥夺优化器使用HASH JOIN
的可能性,HASH JOIN
在许多情况下对此类查询最有效。
有关此方法的更多详细信息,请参阅此文章:
重写查询以便它可以使用600%
导致StartDateTime
次性能提升,但只有当您的日期时间具有一天或更低的准确度时(或者哈希表会变得非常大) )。
由于您的时间组件被剥离了EndDateTime
和CTE
,您可以像这样创建WITH cal AS
(
SELECT CAST('2009-01-01' AS DATE) AS cdate
UNION ALL
SELECT DATEADD(day, 1, cdate)
FROM cal
WHERE cdate <= '2009-03-01'
),
state AS
(
SELECT cdate, ts.*
FROM cal
CROSS APPLY
(
SELECT TOP 1 *
FROM TransactionState
WHERE StartDateTime <= cdate
ORDER BY
StartDateTime DESC
) ts
WHERE ts.EndDateTime >= cdate
)
SELECT *
FROM factTable
JOIN state
ON cdate = DATE(factDate)
:
100
如果您的日期范围超过MAXRECURSION
个日期,请在CTE
上调整{{1}}选项。
答案 1 :(得分:1)
请注意,IDENTITY(1,1)
是在该列中自动生成值的声明。这与PRIMARY KEY
不同,后者是将列作为主键聚簇索引的声明。这两个声明意味着不同的东西,如果你不说PRIMARY KEY
,就会产生性能影响。
答案 2 :(得分:1)
您也可以使用SSIS加载DW。在 slowly changing dimension (SCD)转换中,您可以设置如何处理每个属性。如果选择了历史属性,则将类型2 SCD应用于整行,并且转换将处理细节。如果您更喜欢start_date
,end_date
或current/expired
列,也可以进行配置。
这里要区分的是主键和业务(自然)键之间的区别。主键唯一标识表中的行。业务键唯一标识业务对象/实体,并且可以在维度表中重复。每次应用SCD 2时,都会插入一个新行,并使用新的主键,但使用相同的业务键;然后将旧行标记为已过期,而将新行标记为当前 - 或者相应地填充开始日期和结束日期字段。
DW不应公开主键,因此来自OLTP的传入数据包含业务键,而主键的分配受DW控制; IDENTITY int适用于维度表中的PK。
很酷的是,SSIS中的SCD转换可以解决这个问题。