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


12

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

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

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

其他人则建议有一个时区桥接表,尽管这在一定程度上是有意义的,但似乎也很复杂,需要进行额外的连接才能完成我的客户端应用程序和报告应该可以从某个日期轻松确定的事情(报告主要基于网络)那里有许多库可帮助您转换,显示和格式化日期)。

我唯一能想到的是按日期和小时分组的简便性和可能的​​性能,但实践的糟糕之处在于按日期部分分组(我们正在使用MS SQL,但我们将查询数百万行)或我们应该考虑只是非常简单的日期和时间维度,而在大多数情况下,如星期一之类的大多数文字,时,日,月和年的数字最多不超过几小时,那么在时区发挥作用时就没有多大意义了?


1
我认为您需要的是datetimeoffset数据类型,然后将所有日期存储在其UTC表示中。然后,当您需要提取数据时,可以使用UTC值查询数据,并让客户端以其本地时间表示。
艾伦·汉森

6
我可以认为没有理由我希望独立于时间存储日期。将所有内容存储为UTC日期时间,并让表示层担心本地化。
billinkc

1
我同意@billinkc。我不确定当您不断地将日期和时间放在一起进行时区转换时,分别存储日期和时间会带来什么好处。
2013年

2
@billinkc:“我想不出我想独立于时间存储日期的原因。” - 我可以。每当您在仓库外建立多维数据集时。具有单独的“日期”和“每日时间”维度是司空见惯的最佳做法。
米奇小麦

@MitchWheat您能帮助我理解这一点吗(也许您正在编写答案)?我是一家成年公司,全球销售,格林尼治标准时间2300,我的销售量猛增。我将切片器拖入报告中,并确保在美国东部和中部时区,当人们在回家的路上拿起一些包装好的饮料时,我可能会有一些销售,但是在印度,它是0330,那时没有人在捡翠鸟。珀斯(Perth)的凌晨6点,你们全都强大起来了,但是谁在用VB刷牙呢?取而代之的是,人们在下班后购买酒,所以价格为1700欧元,但我然后需要担心日期界限
billinkc 2014年

Answers:


7

首先...

分离Datime/Time到一个Date维度和Time层面肯定是要走的路。

要管理多个时区,您需要复制DateKey和,TimeKey以便您具有以下内容:

  • LocalDateKey
  • LocalTimeKey
  • UtcDateKey
  • UtcTimeKey

你说...

我所遇到的问题是,在UTC + 2之后的所有时区中,UTC的2013年12月31日(星期二)晚上11:00是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 

最后...

当你正在构建一个数据集市,而不是OLTP数据库,本地和UTC时间的产生应该在你的ETL进行不要在有以下原因的任何客户端应用程序(除了的UTC时间本地化报告读者的观点):

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

为什么要使用单独的尺寸DateTime尺寸而不是单个尺寸DateTime?事实表可能有多个日期,并且累加起来可能会存储两个INT,而不是每个存储一个。
所有行业的乔恩2014年

1
@Jon of All Trades:分开的日期和时间维度是一种常见的最佳做法。它降低了整体维数基数,实际上,我们经常按日期和时间进行切片,或者按日期进行过滤,然后按时间进行切片。
米奇·

0

对于这个答案的简短,我提前表示歉意,并计划在不工作时进行详细说明。

拥有日期和时间表无疑是最有利的,因为它们可以轻松汇总数据。在许多情况下,这是按月或工作日分类这种性质的最简单方法。但是,这不一定取代时间戳的有用性。在您的特定情况下为UTC时间戳。一旦有了该时间戳记,您要做的就是将其更改为报表或表示层中的本地时间。为了避免范围扫描,请确保将请求范围也转换为UTC时间。

如果有其他问题或意见,请随时提出。


1
这不能回答问题。
米奇·
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.