我对事实表粒度的理解是否正确?

Chr*_*ich 8 database-design facttable dimensional-modeling

我和我们公司的另一位 DBA 的任务是审查供应商为我们开发的数据库设计。供应商表示他们使用 Kimball 作为其设计的基础。(注意:我不是在寻找 Kimball 与 Inmon 等的论点。)他们设计了一个具有多个事实和维度的集市。

现在平心而论,我们公司从来没有设计过一个单一的市场。我们一直让顾问这样做。我们从来没有被派去上课或做任何事情。所以我们对仓储/集市/维度建模等的知识是基于我们所拥有的一点经验,我们可以在互联网上找到的内容,以及自读(我们有 Inmon 和 Kimball 的书,并正在努力通过它们) .

既然已经为我的知识水平设置了舞台,我们就来到了设计挑战。

有一个名为“索赔损失统计”的事实表(用于保险)。他们试图同时获取索赔的付款(累计到每月的水平),然后是准备金中的资金(有点像索赔的银行账户)。他们希望看到每月的付款金额(没什么大不了的)。但他们希望看到准备金的账户当前余额。

我举一个形象的例子。

假设我们为索赔设置了 1000 美元的准备金。这被搁置了(所以在某些方面它的功能有点像银行账户)。

2014 年 10 月,我们尚未支付任何款项。因此,企业希望查看 10 月底的付款和准备金余额。

-----------------------------------------------
-  MONTH_YEAR  -  PAYMENTS -  RESERVE_BALANCE -
-----------------------------------------------
-      102014  -      0.00 -          1000.00 -
-----------------------------------------------
Run Code Online (Sandbox Code Playgroud)

然后十一月来了。我们支付 100 美元、150 美元和 75 美元。他们希望看到这些合计金额和余额中的准备金如下:

-----------------------------------------------
-  MONTH_YEAR  -  PAYMENTS -  RESERVE_BALANCE -
-----------------------------------------------
-      102014  -      0.00 -          1000.00 -
-----------------------------------------------
-      112014  -    325.00 -           675.00 -
-----------------------------------------------
Run Code Online (Sandbox Code Playgroud)

然后说我们在 12 月付款为零,然后在明年 1 月再付款 200 美元。

-----------------------------------------------
-  MONTH_YEAR  -  PAYMENTS -  RESERVE_BALANCE -
-----------------------------------------------
-      102014  -      0.00 -          1000.00 -
-----------------------------------------------
-      112014  -    325.00 -           675.00 -
-----------------------------------------------
-      122014  -      0.00 -           675.00 -
-----------------------------------------------
-       12015  -    200.00 -           475.00 -
-----------------------------------------------
Run Code Online (Sandbox Code Playgroud)

这是我奋斗的地方。我的理解是付款部分是正确的。它们都在每个记录中按月级别汇总。因此,如果您需要年份、季度等,您可以进一步汇总。

但储备金额不同。这是一种平衡。企业希望了解每个月的余额有多少。但是你不能在这个领域聚合。如果你这样做了,你会得到一些不稳定的结果。

不知何故,这让我觉得是错误的。但我不能诚实地说我已经足够建模或知道足够多。我只能说我所知道的。据我所知,事实中的所有值都应该具有相同的粒度。

这两个数字都处于“月”的相同粒度,但从它们所代表的角度来看,它们并非如此。一个是一个月内的合计美元。另一个只是平衡。

这样对吗?我一直在反对这个设计。我这样做有错吗?事实上这样做可以吗?或者我对糟糕设计的“代码味道”的感觉是否准确?

任何帮助,将不胜感激。注意:请不要只说“它应该是 X 方式”,请解释为什么它应该是这样,以便我可以从中学习。

编辑:嗯,我了解到我对事实的最初理解是错误的。粒度不是每月。粒度是事务级别。因此,这意味着在 MONTH_YEAR 内(即实际上是财务报告期)将有多个付款和回收交易。这些将按日期或交易日期发布。但由于企业看到的先前报告,以及数据如何存储在遗留系统中,他们希望将交易数据(每行)和储备月余额(每月一行)放在一起)。

一旦我了解到这一点,我意识到问题与其说是添加与非添加,甚至是半添加,不如说是谷物,这是我从一开始就怀疑的问题。我们的 DBA 团队与项目团队讨论了这个问题,并报告说他们试图将两种不同的谷物放在同一个事实中,这是不正确的。他们应该将交易分配到每月级别,然后允许他们获得付款、回收和每月准备金余额(即半加成事实),因为一切都将按月计算。或者他们需要找到一种方法将准备金余额分解为交易,以保留交易级别的粮食。或者他们需要将事实分解为两个事实。一个可以是准备金余额的月度水平。另一个可以在交易级别进行支付和回收。(没有理由他们也不能在每月水平事实中也将付款和回收额放在每月水平。仅取决于业务需求。)

鉴于我所学到的,我会将托马斯的答案标记为正确的答案。但是,我觉得我从原始问题开始的讨论仍然是一个很好的可供其他人学习的讨论,因此我将保留问题的原始部分。我还打算奖励 nikadam 的答案,因为它教会了我很多关于可加性、非可加性和半可加性事实的知识,并纠正 我对维度建模的许多误解。

Ily*_*sky 7

你是对的:“不同的谷物不能混合在同一个事实表中”。

但月末准备金余额和月末支付总额是同一粒。它只是事实之一是半可加的。事实类型(添加与否)不定义表的粒度。

根据您的描述,我将您的谷物视为“每月索赔快照”,这使您的事实表成为“定期快照事实表”。

这篇文章中, Kimball 在同一个事实表中有一个加性和半加性事实的例子。

以下是来自The Data Warehouse Toolkit(第 116 页)的带有半附加事实的定期快照示例:

Kimball 的数据仓库工具包,第 116 页

最佳实践是拥有交易事实表,以反映最低原子级别的准备金(付款和调整)的每次变化。当您处理索赔时,原子级别通常不是索赔而是子索赔(您的保险公司可能有自己的术语)。通常,每个子索赔将代表索赔的不同方以及每一方的付款/准备金。例如,可能没有支付给被保险人,但支付给贵公司未投保的受伤人员以及支付给医院和律师。

根据 BI 工具的性能,您可以直接使用交易事实表来获取每月付款和余额。或者,您可以每天或月末从事务性更新定期快照事实表。

处理半加成事实的能力将取决于您使用的 BI 层。有些工具能够轻松处理半可加性事实,有些则不能。

Kimball 的主要著作(The Data Warehouse Toolkit)有关于保险的完整章节 (16)。


Tho*_*ser 5

你对代码异味的直觉很好。

您正在处理的reserves 是 Kimball 所说的“半可加性事实”。它不能很好地汇总到季度或年度。

对此的典型解决方案是有两个事实表,一个用于附加事实(payments在您的情况下),另一个用于非附加事实。非可加性事实实际上并不需要在月份级别有一个谷物,您可以将它们一直存储到当天,并且事情仍然可以正常工作。

非可加性事实 的reserve查询方式与其他事实不同。您需要做出一项业务决策:reserve在年份级别是什么意思?是一年的最后一个月,还是一年中几个月的平均值?无论您做出何种选择,您都可以在 Kimball 书籍的非可加性事实章节下找到对此进行建模的解决方案。

请注意,如果您使用诸如 Analysis Services 之类的多维数据集产品,即使您将其全部存储在一个表中,也可能让聚合“正常工作”。但是,我更喜欢将事情分开,这样关系查询更容易编写(并且事实也更容易加载)。

  • 或者,您可以将您的非附加事实“储备金”转换为附加事实“支付到储备金”,这与您现在拥有的“储备金外支付”具有相同的粒度级别。 (4认同)