如何避免星型模式中的事实表之间的连接?
How to avoid joins between fact tables in a star schema?
我正在尝试使用星型模式为我的数据仓库建模,但我在避免事实 tables 之间的联接时遇到了问题。
为了对我的问题有个简单的了解,我想收集在我的操作系统上发生的所有事件。因此,我可以创建一个事实 table event
,其维度如 datetime
或 user
。问题是我想收集不同类型的事件:硬件事件和软件事件。
问题是这些事件的维度不同。例如,对于硬件事件,我可以有 physical_component
或 related_driver
维度,对于软件事件,我可以有 software_name
或 online_application
维度(这只是一些例子,要记住的是,event
可以专门用于某些具有特定维度的特定事件)。
在关系模型中,我会像这样组织 3 个 table:
问题是:如何处理星型模式中事实 table 之间的联接?
我想象了 4 个想法,但我不确定其中一个是否适合这种情况。
第一个是保留关系数据库中使用的模型并添加维度table这样:
在这种情况下,问题是我们在事实 table 之间仍然有连接,并且需要在我们所有的查询中使用 JOIN
SQL 语句。
第二个 是仅创建 2 个事实 tables 将复制共享维度(日期时间和用户)并创建一个实体化视图事件,该事件汇总所有事件:
这里的问题是:如果我想对物化视图进行查询会怎样?根据我在 Oracle 文档中阅读的内容,我们不必直接在物化视图上进行查询,但我们必须让查询重写过程发挥作用。
第三个只创建一个事实table,它将包含事件(硬件或软件)的所有可能信息:
这一次,问题是我的 table 将包含很多 NULL
值。
而最后一个是创建3个事实table(这次没有物化视图),如下所示:
这一次,问题是所有事件都存在于事实 table event
及其自身 table 中。因为我们将存储大量数据,所以我不确定这种复制是个好主意。
那么最好的解决方案是什么?或者是否存在第五种解法?
在您的场景中似乎没有理由合并或link这两种类型的事件。话虽如此,您可能有一些您没有描述的原因(例如,从许多系统收集日志并希望轻松地将它们放在一起查看)。
所以我的建议是使用硬件和软件维度键来制作一个事实 table。其中之一始终为 0 或 -1(= 默认 'n/a' 记录)。
这使您无需 UNION 语句或其他复杂的逻辑就可以将它们聚合在一起,甚至可以支持 link 如果它们在将来出现时同时出现在硬件和软件上的事件。
您可以 never/rarely 将事实表连接在一起。您可以加入共享(一致)维度的聚合事实(即每小时的软件事件数与每小时的硬件事件数相比)。
对我来说,在查看维度建模时,您始终必须考虑将要提出的各种问题。
根据您的描述和您对其他答案的后续评论,我认为选项 2 或选项 4 是从维度建模的角度建模事物的正确方法。每个事实都应该是业务流程的衡量标准,软件和硬件事件的维度似乎差异很大,因此需要单独存储。
然后,有一种情况也可以将单独的事件 table 存储为视图、实体化视图或普通视图 table 存储常见的事物。
一旦确定这是建模事物的正确方法 'logically',您就需要平衡性能、可维护性、可用性和存储。
对于维度建模,查询的可用性和性能是重中之重(否则你可能根本不使用维度模型),ETL 中的额外工作和额外 space 需要付出的代价是值得的。
非物化视图会以性能为代价为您节省 space,但您可以为它提供一个或两个足够出色的索引来减轻这种情况。实体化视图将以存储为代价提供性能。
我很想创建带有索引和非物化视图的两个事实 table,并在采取进一步的性能增强步骤之前查看它的性能。 1000 万个事实行还不错,它可能仍然有效。
实体化视图可以直接查询。但是,如果您愿意,可以使用 Oracle 的查询重写功能,以便在查询原始 table 时将物化视图用作性能增强器,如索引。
详情请看这里:http://www.sqlsnippets.com/en/topic-12918.html
您是选择在查询重写模式下使用它还是仅作为视图本身取决于您是想让用户了解这个额外的 table,还是让它作为一个有用的朋友坐在后台.
事件应该是单一事实。如果将它们一分为二,则很难对两者进行聚合。
如有必要,您可以有单独的硬件和软件属性维度,但您应该有一个通用的事件维度,即使它只是具有一些简单属性的垃圾维度,例如类型(hardware/software)、重要性(高、低)等
附带说明一下,我通常看到带有箭头的图表,这些箭头来自事实和维度。事实上 table 键查看尺寸而不是相反。
我正在尝试使用星型模式为我的数据仓库建模,但我在避免事实 tables 之间的联接时遇到了问题。
为了对我的问题有个简单的了解,我想收集在我的操作系统上发生的所有事件。因此,我可以创建一个事实 table event
,其维度如 datetime
或 user
。问题是我想收集不同类型的事件:硬件事件和软件事件。
问题是这些事件的维度不同。例如,对于硬件事件,我可以有 physical_component
或 related_driver
维度,对于软件事件,我可以有 software_name
或 online_application
维度(这只是一些例子,要记住的是,event
可以专门用于某些具有特定维度的特定事件)。
在关系模型中,我会像这样组织 3 个 table:
问题是:如何处理星型模式中事实 table 之间的联接?
我想象了 4 个想法,但我不确定其中一个是否适合这种情况。
第一个是保留关系数据库中使用的模型并添加维度table这样:
在这种情况下,问题是我们在事实 table 之间仍然有连接,并且需要在我们所有的查询中使用 JOIN
SQL 语句。
第二个 是仅创建 2 个事实 tables 将复制共享维度(日期时间和用户)并创建一个实体化视图事件,该事件汇总所有事件:
这里的问题是:如果我想对物化视图进行查询会怎样?根据我在 Oracle 文档中阅读的内容,我们不必直接在物化视图上进行查询,但我们必须让查询重写过程发挥作用。
第三个只创建一个事实table,它将包含事件(硬件或软件)的所有可能信息:
这一次,问题是我的 table 将包含很多 NULL
值。
而最后一个是创建3个事实table(这次没有物化视图),如下所示:
这一次,问题是所有事件都存在于事实 table event
及其自身 table 中。因为我们将存储大量数据,所以我不确定这种复制是个好主意。
那么最好的解决方案是什么?或者是否存在第五种解法?
在您的场景中似乎没有理由合并或link这两种类型的事件。话虽如此,您可能有一些您没有描述的原因(例如,从许多系统收集日志并希望轻松地将它们放在一起查看)。
所以我的建议是使用硬件和软件维度键来制作一个事实 table。其中之一始终为 0 或 -1(= 默认 'n/a' 记录)。
这使您无需 UNION 语句或其他复杂的逻辑就可以将它们聚合在一起,甚至可以支持 link 如果它们在将来出现时同时出现在硬件和软件上的事件。
您可以 never/rarely 将事实表连接在一起。您可以加入共享(一致)维度的聚合事实(即每小时的软件事件数与每小时的硬件事件数相比)。
对我来说,在查看维度建模时,您始终必须考虑将要提出的各种问题。
根据您的描述和您对其他答案的后续评论,我认为选项 2 或选项 4 是从维度建模的角度建模事物的正确方法。每个事实都应该是业务流程的衡量标准,软件和硬件事件的维度似乎差异很大,因此需要单独存储。
然后,有一种情况也可以将单独的事件 table 存储为视图、实体化视图或普通视图 table 存储常见的事物。
一旦确定这是建模事物的正确方法 'logically',您就需要平衡性能、可维护性、可用性和存储。 对于维度建模,查询的可用性和性能是重中之重(否则你可能根本不使用维度模型),ETL 中的额外工作和额外 space 需要付出的代价是值得的。
非物化视图会以性能为代价为您节省 space,但您可以为它提供一个或两个足够出色的索引来减轻这种情况。实体化视图将以存储为代价提供性能。
我很想创建带有索引和非物化视图的两个事实 table,并在采取进一步的性能增强步骤之前查看它的性能。 1000 万个事实行还不错,它可能仍然有效。
实体化视图可以直接查询。但是,如果您愿意,可以使用 Oracle 的查询重写功能,以便在查询原始 table 时将物化视图用作性能增强器,如索引。 详情请看这里:http://www.sqlsnippets.com/en/topic-12918.html 您是选择在查询重写模式下使用它还是仅作为视图本身取决于您是想让用户了解这个额外的 table,还是让它作为一个有用的朋友坐在后台.
事件应该是单一事实。如果将它们一分为二,则很难对两者进行聚合。
如有必要,您可以有单独的硬件和软件属性维度,但您应该有一个通用的事件维度,即使它只是具有一些简单属性的垃圾维度,例如类型(hardware/software)、重要性(高、低)等
附带说明一下,我通常看到带有箭头的图表,这些箭头来自事实和维度。事实上 table 键查看尺寸而不是相反。