处理数据集市/仓库中的时区

Ves*_*kov 14 data-warehouse sql-server-2012 timezone datetime

我们开始设计数据集市/仓库的构建块,我们需要能够支持所有时区(我们的客户来自世界各地)。从在线(和书籍)阅读讨论来看,一个常见的解决方案似乎是在事实表中具有单独的日期和时间维度以及时间戳。

但是,我很难回答的问题是,考虑到我的动态时区要求,日期和时间维度实际上对我有什么好处?时间维度更有意义,但我很难处理日期维度。日期维度的一般设计方法通常包括日期名称、星期几、月份名称等属性。我遇到的所有问题是 UTC 时间 2013 年 12 月 31 日星期二晚上 11:00 是星期三, 2014 年 1 月 1 日,在 UTC+2 之后的所有时区。

因此,如果我必须对每个查询(和报告)进行所有这些时区转换,那么拥有和存储这些我可能永远不会使用(似乎)的属性有什么意义?有些人建议为每个时区设置事实行,但这对我来说似乎很荒谬。我们需要能够每月存储数百万条记录。

其他人建议有一个时区桥接表,虽然有一定的意义,但它似乎也需要额外的复杂性和额外的连接来完成我的客户端应用程序和报告应该能够轻松地从日期中找出的东西(报告将主要基于网络那里有无数的库可以帮助转换、显示和格式化日期)。

我唯一能想到的是按日期和小时分组的简便性和可能的​​性能,但是按日期部分分组的做法有多糟糕(我们正在使用 MS SQL,但我们将查询数百万行),或者我们应该考虑只是非常简单的日期和时间维度,大多数情况下不超过小时、日、月和年数字,因为大多数文字(例如星期一)在时区发挥作用时没有多大意义?

Adr*_*rie 8

首先...

拆分Datime/Time成一个Date维度和一个Time维度肯定是要走的路。

要管理多个时区,您需要复制DateKeyTimeKey以便您拥有以下内容:

  • LocalDateKey
  • LocalTimeKey
  • UtcDateKey
  • UtcTimeKey

你说...

我遇到的所有问题是 UTC 时间 2013 年 12 月 31 日星期二晚上 11:00 是 UTC+2 之后的所有时区的 2014 年 1 月 1 日星期三。

通过拥有我上面列出的 4 列,将能够使用表别名将事实表连接到日期和/或时间维度(在 Kimball 术语中,这些别名维度表被称为“角色扮演维度”),因此你会有如下内容:

/*
    Assumes the following:
        - [DateLongName] has the format of this example "Tuesday, December 31, 2013"
        - [TimeShortName] has the format of this example "11:00 PM"
        - Both [DateLongName] & [TimeShortName] are strings
*/
select
    -- Returns a string matching this example  "11:00 PM Tuesday, December 31, 2013"
    localTime.TimeShortName + ' ' + localDate.DateLongName
    ,utcTime.TimeShortName + ' ' + utcDate.DateLongName
    ,f.*
from
    FactTableName  AS f

    -- Local Date and Local Time joins          
    inner join dbo.Date  AS localDate
        on localDate.DateKey = f.LocalDateKey

    inner join dbo.Time  AS localTime
        on localTime.TimeKey = f.LocalTimeKey 

    -- Utc Date and Utc Time joins    
    inner join dbo.Date  AS utcDate
        on utcDate.DateKey = f.UtcDateKey

    inner join dbo.Time  AS utcTime
        on utcTime.TimeKey = f.UtcTimeKey 
Run Code Online (Sandbox Code Playgroud)

在结束...

由于您正在构建数据集市,而不是 OLTP 数据库,因此本地和 Utc 时间的生成应在您的 ETL 中执行,而不是在任何客户端应用程序中执行,原因如下(除了将 UTC 时间本地化为报告读者的观点):

  • 将计算驻留在任何查询中会给它们带来额外的性能负担,乘以您必须为您拥有的任何报告运行所述查询的次数(这在读取数百万行时很重要)
  • 确保在每个查询中正确维护计算的额外负担(特别是当您考虑夏令时时)
  • 防止对该列所属的任何索引进行范围扫描,因为您将对列执行计算,这会强制查询执行索引扫描而不是搜索(这通常更昂贵,因为需要读取每个数据页);这被称为不可sargable
    • 由于评论而编辑:如果您将转换下推到实际查询中,则适用
  • 使用提供额外 UTC 日期和时间的概念,没有什么能阻止您采用此概念并通过调用 thisStandardisedDateKeyCorporateHQDateKey来扩展它,或者,您根据其他一些业务商定的标准标准化而不是 UTC 日期表
  • 拥有两种单独的列类型(本地和 UTC),允许跨地理距离进行并排比较。想想 -> 澳大利亚的某个人输入了一条带有本地和 UTC 时间戳的记录,纽约的某个人阅读了带有本地(澳大利亚)日期和时间以及UTC 日期和时间的纽约表示的报告,从而看到了一些东西他们的澳大利亚同行在中午(澳大利亚时间)发生的事情发生在他们时间(纽约时间)的深夜。这种时间的比较在跨国企业中是必不可少的。