如何在维度表中查找未使用的行

Posted

技术标签:

【中文标题】如何在维度表中查找未使用的行【英文标题】:How to find unused rows in a dimension table 【发布时间】:2020-09-04 13:22:21 【问题描述】:

我的数据库中有一个维度表变得太大。我的意思是它有太多的记录——超过一百万——因为它的增长速度与关联的事实相同。这主要是由于设计不好,我正在尝试清理它。

我尝试做的一件事是删除不再使用的维度记录。定期维护事实表并删除旧快照。因为维度不是这样维护的,所以表中有许多行的主键值不再出现在任何链接的事实表中。 所有事实表都有外键约束。

有没有办法找到主键值不再出现在与外键约束链接的任何表中的表行?

我尝试编写脚本来跟踪这一点。基本上是这样的:

select key from dimension 
where not exists (select 1 from fact1 where fk = pk) 
and not exists (select 1 from fact2 where fk = pk) 
and not exists (select 1 from fact3 where fk = pk)

但是对于很多链接表,这个查询会在一段时间后死掉 - 至少,我的管理工作室崩溃了。所以我不确定是否还有其他选择。

【问题讨论】:

请以格式化文本而不是图像的形式提供示例数据和所需的输出。 这永远不会很快。最方便的方法是生成遍历所有事实表的查询,以将每个维度列的DISTINCT 值选择到临时表中,然后删除该表中未出现的维度行。这些列上的(非聚集)列存储索引将大大加快速度(并且通常在仓库中可能是一件好事)。 是的,我有点害怕会变成这样。实际上,我已经编写了代码来生成执行此操作的语句。但至少现在我知道我没有错过更好的方法来做到这一点。 【参考方案1】:

我们不得不在我的一位客户身上做类似的事情。查询,就像你的“不存在......并且不存在......并且不存在......”在我们改变我们的策略以在大约 20 分钟内处理这个问题之前需要大约 22 小时才能运行。

正如 Nsousa 建议的那样,您必须拆分查询,这样 SQL Server 就不必一次性处理所有数据,不必使用 tempdb 和所有其他东西。

首先,创建一个包含所有键的新表。创建此表的原因是不必为每个查询读取全表扫描,在 8k 页面上有更多键,并且在每次删除后处理越来越小的键集。

create table DimensionkeysToDelete (Dimkey char(32) primary key nonclustered);
insert into DimensionkeysToDelete 
select key from dimension order by key; 

然后,不是删除未使用的键,而是删除事实表中存在的键,从行数最少的事实表开始。 确保事实表具有适当的索引以提高性能。

delete from DimensionkeysToDelete 
from DimensionkeysToDelete d 
inner join fact1 on f.fk = d.Dimkey;

delete from DimensionkeysToDelete 
from DimensionkeysToDelete d 
inner join fact2 on f.fk = d.Dimkey;

delete from DimensionkeysToDelete 
from DimensionkeysToDelete d 
inner join fact3 on f.fk = d.Dimkey;

一旦完成所有事实表,DimensionkeysToDelete 中只会保留未使用的键。要回答您的问题,只需在此表上执行选择以获取该特定维度的所有未使用键,或将其与维度连接以获取数据。

但是,据我了解您需要清理仓库,使用此表从原始维度表中删除。在这一步,您可能还需要为审计目的采取一些措施(即:在审计表中插入 'Key' + key + ' deleted on + convert(datetime, getdate(),121) + ' by script X'.. ..)

我认为这可以优化,看看执行计划,但我的客户对此很满意,所以我们不必花太多精力。

【讨论】:

冒着明显的风险 - 我假设您要删除记录的维度都不是 SCD2(或类似)?如果是这样,您显然会遇到更复杂的问题,因为您需要修复剩余记录的开始/结束日期以消除任何空白【参考方案2】:

您可能希望将其拆分为不同的查询。检查 fact1 中未使用的行,然后分别检查 fact2 等。然后将所有这些结果相交以获得所有事实表中未使用的行。

我还建议使用左外连接代替嵌套查询,计算事实表中每个 pk 的行数,并从结果集中过滤掉那些计数不为零的行。

您的查询会很困难,因为它会同时扫描每个事实表。

【讨论】:

以上是关于如何在维度表中查找未使用的行的主要内容,如果未能解决你的问题,请参考以下文章

Oracle - 删除维度表中的一行很慢

如果维度/事实表中的数据未正确加载,我需要执行哪些步骤来清理数据

慢慢改变尺寸

数据仓库星型模式的维度表和事实表中的数据如何?

BIEE04_当维度表中的维不存在事实表中,需要展示所有维度并且数据类展示为0

基于链接到维度表之一的事实表中的键添加新维度