2016-12-07 61 views
4

我加载数据到表中以下列方式:删除VS回滚策略 - ETL负载

DECLARE @srcRc INT; 
DECLARE @dstRc INT; 

SET @srcRc = (SELECT COUNT(*) FROM A) 

INSERT INTO t 
     (Col1 
     ,Col2 
     ,Col3 
     ) 
     SELECT A.Col1 
       ,A.Col2 
       ,B.Col3 
     FROM A 
       JOIN B 
        ON A.Id = B.Id; 

SET @dstRc = @@ROWCOUNT 

现在我比较变量@srcRc@dstRcROWCOUNT必须相同。如果不是,则需要删除插入的行。

Q1:回滚插入行的最佳策略是什么?

我有几个想法:

1)运行负荷在交易和回滚,如果行数不匹配。
2)标志列(位)添加到名为toBeDeleted目标表,运行负荷,如果行数不匹配,与1价值,将其标记为候选删除更新toBeDeleted列。然后删除批处理模式(while-loop)。
或者不要删除它们,但在使用t表时,始终排除查询中的删除候选项。
3)插入行之前,首先比较行数。如果不匹配,请不要启动负载。

DECLARE @srcRc INT; 
DECLARE @dstRc INT; 
SET @srcRc = (SELECT COUNT(1) FROM A); 
SET @dstRc = (SELECT COUNT(1) FROM A JOIN B ON A.Id = B.Id); 

Q2:什么是更高金额的行更好的解决方案,让我们说10-100万?
问题3:还是有类似的情况下更好的策略?

回答

0

OK,假设:

您需要回滚到一些以后工作时,表A和B的内容可能已经改变

也有可能是你别其他行不想删除作为回滚的一部分。

,那么你必须让你插入的行的名单,因为你无法可靠地再生由A和B名单,你不能只在T

删除一切

您可以通过两种方式

做到这一点
  • 更改您的导入,以便它首先将行插入到导入表中,使导入表保持四处移动,直到您确定不再需要它为止。

  • 添加一个额外的列T [importId]您在其中放了唯一标识值

显然,第一个策略使用了更多的磁盘空间。因此,保存数据的时间越长,数据越多,额外列的外观就越好。

另一种选择是单独生成导入数据的列表,并将您的事务sql作为批量插入,并将所有数据硬编码到sql中。

这适用于小列表,初始设置数据等。


编辑:

从您的评论听起来好像你不想卷每本身回来。但是,在导入过程中应用业务逻辑的最佳方式。

在这种情况下,您的第三个答案是最好的。当您知道源数据不正确时,请勿进行导入。

+0

我只需要回滚“当前”负载,而不是历史。所以通常我一天一天地加载。今天我加载日期N,明​​天N + 1。所以只检查当前批次的行数。 如果rowcount不匹配,则所有来自当前加载的内容都需要被擦除,而不仅仅是一些行。 – DNac

+0

这些情况的麻烦在于它不是真正的回滚,除非你撤销你做的任何事情。任何依赖简单行数的东西都可能出错。例如,您复制行x并跳过行y。你的排数将匹配 – Ewan

+0

这是真的,但这种情况从来没有发生过,我认为这是非常罕见的。 – DNac