在SSIS错误中查找转换:不会阻止插入现有记录

时间:2019-02-08 09:40:42

标签: sql-server ssis etl lookup

我有从源读取的SSIS包,执行查找转换,以检查记录是否在目标中,如果存在,则将其重定向以匹配输出并更新它,否则将其不匹配并插入。问题在于有时它会插入一条记录,该记录应重定向以进行更新。这是通过作业完成的,如果我手动执行程序包,一切都很好。使用匹配列正确设置了查找组件。

我不知道为什么会这样,最愚蠢的是我无法调试它,因为手动一切都很好。

有什么想法吗?

1 个答案:

答案 0 :(得分:2)

在有插入内容应该是更新的情况下,有两个选项。

重复的源值

首先,您的源数据中有重复的键,而目标表中没有任何键。

源数据

Key|Value
A  |abc
B  |bcd
A  |cde

目的地数据

Key|Value
C  |yza
B  |zab

在这种情况下,假设在包开始执行之前Lookup组件具有默认行为,即完全缓存,SSIS将运行Lookup参考表的源查询。只有所有的查询表数据都已被缓存后,数据流才会成为流动数据。

  • 第一行A:abc命中查找。不,没有数据,并且转到了插入路径。
  • 第二行B:bcd命中查找。不,没有数据,并且转到了插入路径。
  • 第三行A:cde命中查找。不,没有数据,无法进入插入路径(并且希望发生主键/唯一键冲突)

当程序包启动时,它只知道目标表中的数据。在运行期间,您向表中添加了相同的键值,但从未要求查询组件检查更新。

在这种情况下,有两种解决方法:第一种是将缓存模式从“完全”更改为“无”(或“部分”)。这将使查找组件针对流过数据流的行的目标表发出查询。对于大行而言,这可能会变得昂贵。它也不是万无一失的,因为数据流具有缓冲区的概念,并且在示例3行加载的情况下,它们都适合放在一个缓冲区中。缓冲区中的所有行将在大约同一时间命中“查找”,因此,当第三行流经组件时,目标表仍将不包含A值。您可以通过将缓冲区大小调整为1来阻止数据流并强制其一次处理一行,但这通常不是一个好的解决方案。

另一个解决方案是重复数据删除/处理生存。如果我们的源对于同一业务密钥具有不同的值,则应该将其放入数据库的哪一行?首先,最后选择一个?如果您无法在数据到达“数据流”之前消除数据,那么您将需要使用“聚合”组件对数据进行重复数据删除,以最大程度地汇总数据。

区分大小写的查询

源数据

Key|Value
A  |abc
B  |bcd
a  |cde

目的地数据

Key|Value
C  |yza
B  |zab

查找组件咬住您的另一种情况是,默认的完全缓存匹配基于字符串的.NET匹配规则。因此,AAA不等于AaA。如果您的查询正在进行字符串匹配,即使您的数据库不区分大小写 ,SSIS查询也不会不敏感。

在需要匹配Alpha数据的情况下,通常会在源数据中添加一个多余的/重复的列,这是全部为大写或小写形式的关键数据。如果查询数据,则将其添加到查询中。如果要从平面文件加载,则可以使用派生列组件将列添加到数据流中。

然后,当我使用Lookup组件时,确保引用表中的数据大小写相同。

查找组件警告

全缓存模式: -对参考数据的更改不敏感 -区分大小写的匹配 -总的来说更快 -延迟数据流,直到缓存了查询数据为止 -NULL匹配空字符串 -缓存的数据需要RAM

无缓存模式: -对参考的变化敏感 -区分大小写匹配基于查找系统的规则(DB区分大小写,您将获得敏感匹配) -这取决于(100行源数据,1000行参考数据-没有人会注意到。  1B行的源数据和10B行的参考数据-有人会注意到。是否有索引来支持查找等) -NULL不匹配 -没有明显的SSIS内存开销

部分缓存: 部分缓存与“无缓存”选项几乎一样,除了部分缓存与参考表匹配之后,它将缓存该值直到执行结束或由于内存压力而被推出

Lookup Cache NULL answer