4

有两种思想流派:

  1. 使用代理键,最好采用以下格式:YYYYMMDD,因为这将始终是连续的。

  2. 消除 Date 维度代理键并改用实际日期。

我对维度建模专家的问题是:

1> Which design would you prefer and why?

2> How should we handle unknown values in each of the cases, Can we simply place 
   NULL in Fact table for unknown dates as Foreign Key can be NULL (if not why)?

3> If we need to partition fact table on date column, how would we achieve that 
   in case 1.

我倾向于使用实际日期并使用 NULL 来表示事实表中的 UNKNOWN 日期,因为无需查看维度表即可对事实进行与日期相关的验证。

4

3 回答 3

4

为了你问:

  1. Kimball 大谈特谈日期的代理键,但我还没有看到一个令人信服的技术论据支持这样做。转换为 YYYYMMDD 格式意味着您必须转换日期或加入日期维度以进行日期算术。这两种方法都有多种方式可以通过 .
    SQL Server 上的日期时间为 8 个字节,Oracle 上的 (IIRC) 为 7 个字节,因此它比整数代理宽一点,但除非您有非常大的数据量,否则我不再认为这个论点有任何优点。优化器只是将日期视为幕后的数值。

  2. 我对一种或另一种类型的“特殊”值有要求。根据您希望它们如何排序,您可以使用各种值。在过去,我曾多次使用此方案:

    • 1800-01-01 表示“以前的”。除非您需要比这更早的日期,否则这将在开头进行排序。
    • 9000-01-01 表示“正在进行”。这将在最后进行排序。
    • 9100-01-01 表示“未知”。这将在最后进行排序。
    • 9200-01-01 表示“错误”。这将在最后进行排序。
  3. 任何支持它的 DBMS 平台(包括几乎所有主流 RDBMS 平台)上的范围分区在日期或整数分区键上都可以正常工作。

我不建议对数据仓库中的未知值使用 NULL,因为它需要外部连接才能使用数据。这将影响查询计划的效率,并为没有经验的玩家设置数据陷阱。数据仓库中的 NULL 键在很多方面都是不好的魔力。

NULL 键值的另一个问题是大多数临时报告工具不能很好地使用连接中的空键。通常它们会使用内部连接,因此键列中带有 NULL 的行会中断。

对于大多数其他维度,您将使用代理项。这将维度与源数据分离,并允许您将新数据源引入系统而不会破坏现有数据。

在某些情况下,将自然键用作维度键可能很有用。这方面的一个例子可能是 ISO 货币代码或帐号。在前一种情况下,3 个字母的代码足够小,使用它作为密钥的开销很小,并且编码方案(通常)在所有数据源中都是通用的。在后一种情况下,代码通常是数字且足够短,无论如何都可以放入整数,并且通常在整个组织中通用。

这样做的主要好处是您可以让报告专家使用他们自己的查询来操作数据。对于直接使用数据的人来说,它使表格更易读。

于 2012-08-31T13:30:22.453 回答
4

Oracle 的不寻常之处在于它的Date 数据类型包括时间,并且需要 7 个字节。其他平台通常对裸日期有独立的数据类型。SQL Server 的日期占用 3 个字节,PostgreSQL 占用 4 个字节,而 DB2 占用 4 个字节(我认为)。

当您使用格式为 YYYYMMDD 的整数时,您必须在某处编写附加代码以确保这些值是有效日期。20121332 是一个有效的整数,但它不代表一个有效的日期。您不必为日期数据类型编写类似的验证代码。

在单列中记录缺失信息时,这两种选择没有太大区别。您要么使用不代表其他日期含义的日期,要么使用不代表其他整数含义的整数。用很少的数字编码原因(例如,其中“1”可能表示“尚未提供”)意味着您必须将不是有效日期整数的值有效日期整数的值存储在同一列中。

但我认为将某些数据丢失的事实与数据丢失的原因区分开来更有意义。这意味着存储更多数据,而有些人不愿意存储更多数据。


我发现这两本 IBM 红皮书在设计数据仓库时很有用。

锚定建模是最近的发展。以这种方式设计的模式中的大多数表都将位于6NF中。

于 2012-08-31T12:14:45.493 回答
0

1. 最好使用 YYYYMMDD 格式的代理键,因为这将始终是连续的。

2.去掉日期维度代理键,改用实际日期。

使用第一个选项。您使用实际日期,它将占用更多磁盘,索引效率较低,连接效率较低。此外,如果您使用日期类型,您将如何表示“未知日期”、“日期尚不可用”、“日期早于日历日期范围”、“日期晚于日历日期范围”?

您不能对日历维度的所有这些不同的“未知”类型成员使用“01-01-1900”。理想情况下,所有代理键都应该是无意义的,否则报表用户太容易忽略维度。维度增加了维度的丰富性,例如日历维度、日期所属的星期、月份、年份、日期名称等。应通过匿名代理键强制记者使用维度。

在数据仓库的表示层中永远不应该有空值,因为它们会迫使您在事实和维度之间进行左外连接。星型模式的全部意义在于提高查询性能——进行外连接直接违背了这一原则。总是用未知的成员键替换空值,如 -1、-2 等(假设你的“真实”成员键从 1 开始并从那里依次上升)。

为 Catcall 编辑

我建议使用代理键,其中日历中最早的日期获取密钥 1,下一个日期获取 2,依此类推。在星型模式中,事实由代理键组成 - 所有小整数或度量。您必须加入维度才能查看日期 1 代表什么。所有的代理人都没有任何意义。这就是您构建数据集市的方式。用户应该如何记住“01-01-1900”表示“日期不可用”和“01-01-1901”表示“未知”和“01-01-1902”早期日期等?将这些标题存储在维度中并实际上具有代理项-3、-2、-1 不是更好吗?然后用户将在报告中看到标题“未知”或“早期日期”。将日期类型用作代理键只是一个错误,并且会限制有用性,解决方案的效率和灵活性。我通过经验知道这一点。

于 2012-08-31T09:37:21.000 回答