【问题标题】:Data warehouse design - how to design for measures that are time related, such as last 7 days, etc数据仓库设计 - 如何设计与时间相关的度量,例如最近 7 天等
【发布时间】:2012-05-02 12:27:28
【问题描述】:

我正在重新构建一个报告/数据仓库类型的数据库。我们目前有一个表,其中包含酒店粒度的数据(即 HotelID 加上许多度量,包括 Last7DaysGross、Last28DaysXXX 等度量)。

我认为最好转移到位于 Hotel/StayDate 粒度的事实表。但是,对 HotelID 进行分组并包括 Last7DaysGross 等日期相关的度量需要非常好。

什么样的结构可以在这里工作?我认为我不能像我希望的那样使用索引视图,因为它们有多重限制(没有子查询等)。为了获得合理的性能,我需要在酒店级别(从 HotelStayDate 级别聚合?)这是人们最常查询的级别。我是否需要实际创建诸如 Last7DaysGross 之类的字段?这似乎不是一个好的设计,但我很难想出另一个。

抱歉,这个问题有点含糊。还有什么我在这里想念的吗?我知道这些与日期相关的措施通常会在前端级别完成(即在诸如 Business Objects 之类的工具中)。但是,对于这个项目,我们需要将其保存在数据库中。

谢谢, 西尔维娅

编辑:

感谢所有体贴的cmets!我接受了 David Marwick 的回答,因为他有扩大日期维度的想法。我什至没有想到这个想法,听起来很值得一试。

稍微扩展一下 David Marwick 的想法,我想出了这个想法。我可能会尝试看看它是如何工作的:

DateDimension
   DateKey
   DateKeyBeginLast28Days
   DateKeyEndLast28Days

Fact
   DateKey
   GrossTransactions

那么查询时:

Select
   DateKey
   ,SumLast28Day = sum(GrossTransaction)
from Fact
   join DateDimension
      on Fact.DateKey >= DateDimension.DateKeyBeginLast28Days
      and Fact.DateKey <= DateDimension.DateKeyEndLast28Days
group by DateKey

【问题讨论】:

  • 您预计每天有多少笔交易?总计,在所有酒店中,精确到单笔交易?

标签: sql-server data-warehouse


【解决方案1】:

我认为您在 [Hotel, Date] 谷物中放置一张桌子然后卷入酒店的设计听起来不错。正如 Damir 指出的那样,它使您的读取查询变得简单,并且可以轻松地添加/删除未来的聚合度量(请记住,围绕您将来可能有的需求进行设计通常是一个坏主意。 )。

Pondlife 也有好处。您的定性要求可能决定维护聚合表的可行性,例如系统需要多久更新一次(每天、每小时、15 分钟、实时?),测量需要多准确(也许用户只需要粗略了解每家酒店的表现)、读取源交易数据的成本、源交易数据的长期可用性(是否被存档)等。

如果您选择添加 [Hotel, StayDate] 粒度事实表而不维护聚合,那么也许您可以探索维度中的一些技巧以节省时间。可能类似于包含 [date, date_in_last_7_days] 的 7 天日期维度(因此每个日期有 7 条记录),以防直接连接与查询过去 7 天的范围可以为您节省任何时间。这可能是一个愚蠢的例子,但类似的东西。日期尺寸很小。

如果您需要提高性能,最后考虑硬件优化,例如将表移入内存(尤其是维度或非大型事实表)。

【讨论】:

    【解决方案2】:

    聚合事实表在数据仓库中是完全可以接受的。

    如果你还没有准备好,我会推荐下面的书

    DW Toolkit

    在这里,Kimball 指出将事实表预聚合到聚合事实表中很好,但它确实声明它们应该类似于汇总级别的“基本”事实表。

    我怀疑报告字段的介绍应该在您的前端报告工具或多维数据集查看器中。

    【讨论】:

    • 谢谢大卫。我没有聚集到酒店级别的问题。对我来说似乎不正确的是汇总与日期相关的度量(即 Last7DaysGross 等)。
    • 我的理解是这应该在表现层完成。但是,如果这是不可能的,您可以考虑在这些表格之上创建视图,然后将您的报告作为基础?
    • 会同意大卫的观点。您的聚合需求非常适合 OLAP 多维数据集概念。这些主要(并非总是)由表示层构建和管理,即 MicroStrategy、BO 等工具。如果不可能,请接受一些限制,并有固定的聚合度量,1 天、7 天、14 天、30 天sum 等。在日期级别上进行聚合并不是那么糟糕,并且在很多情况下都是必需的。
    【解决方案3】:

    正如 David 所说,预先汇总一些总数(在 ETL 过程中)以使重要的查询运行得更快并没有任何问题。即使在操作数据库中,这也是一种常见的技术,如果您知道某些聚合被频繁使用,那么它在数据仓库中非常有意义。

    因此,您当然可以使用 HotelID, Last7DaysGross, Last28DaysGross 和任意数量的其他聚合创建一个名为 FactHotelRevenueSummary(或任何与您现有命名约定相匹配的名称)的表。

    我认为首先要考虑的要点是:

    • 由于可观察到的性能问题,预聚合确实很有必要,即您正在增加数据库的复杂性以解决实际问题,而不是因为您模糊地认为它可能会有所帮助
    • 您的 ETL 流程会进行检查,以确保聚合数据与“原始”数据完全匹配,否则您将获得不同的数字,具体取决于您查询的事实表,这会对用户信心产生非常负面的影响

    【讨论】:

      【解决方案4】:

      取决于,通常的查询(过去 7 天)看起来像

      select
          HotelName
        , sum(SaleAmount) as Sales
      from factSale as s
      join dimDate  as d on d.DateKey  = s.DateKey
      join dimHotel as h on h.HotelKey = s.HotelKey 
      where DaysAgo between 1 and 7
      group by HotelName 
      ;
      

      但是,假设您有一份报告,其中包括运行总和(跨期间)及其变化。 报告布局可能如下所示:

      | Date | 1-Day | Change-1-Day % | 7-Day | Change-7-Day % | 28-Day | Change-28-Day | 90-Day | Change-90-day % |
      

      不再那么简单了。因此,创建聚合(事实)表要容易得多 使用标准期间的预先计算字段并在该字段上运行查询。

      所以聚合(事实)表可能看起来像

      factRunningSum
      ----------------------------
      DateKey     integer  (PK)
      HotelKey    integer  (PK)
      Sale_1_Day  decimal(19,2)
      Sale_7_Day  decimal(19,2)
      Sale_28_Day decimal(19,2)
      Sale_90_Day decimal(19,2)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-02-16
        • 2011-05-04
        • 1970-01-01
        • 2021-01-23
        • 2017-07-19
        • 2019-01-21
        • 2020-08-19
        • 1970-01-01
        相关资源
        最近更新 更多