我们不得不在我的一位客户身上做类似的事情。查询,就像你的“不存在......并且不存在......并且不存在......”在我们改变我们的策略以在大约 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'.. ..)
我认为这可以优化,看一下执行计划,但是我的客户对此很满意,所以我们不必为此付出太多努力。