3

我正在尝试消除我的 SSIS 进度日志中的一些虚假警告。我收到一堆关于使用原始 SQL 完成工作的任务中未使用列的警告。我有一个数据流负责在加载新数据之前将数据存档在临时表中。数据流如下所示:

+--------------------+
| OLEDB Source task: |
| read staging table |
+--------------------+
          |
          |
+---------------------------+
| OLEDB Command task:       |
| upsert into history table |
+---------------------------+
          |
          |
+---------------------------+
| OLEDB Command task:       |
| delete from staging table |
+---------------------------+

我的“upsert”任务类似于:

--------------------------------------
-- update existing rows first...
update history
set    field1 = s.field1
    ...
from   history h
inner  join staging s
on     h.id = s.id
where  h.last_edit_date <> s.last_edit_date -- only update changed records

-- ... then insert new rows
insert into history
select s.*
from   staging s
join   history h
on     h.id = s.id
where  h.id is null
--------------------------------------

清理任务也是一条 SQL 命令:

--------------------------------------
delete from staging
--------------------------------------

由于 upsert 任务没有任何输出列定义,我在日志中收到一堆警告:

[DTS.Pipeline] Warning: The output column "product_id" (693) on output 
"OLE DB Source Output" (692) and component "read Piv_product staging table" (681) 
is not subsequently used in the Data Flow task. Removing this unused output column 
can increase Data Flow task performance. 

如何消除对这些列的引用?我尝试了一些不同的任务,但似乎没有一个能让我“吞下”输入列并从任务的输出中抑制它们。我想保持我的日志干净,所以我只看到真正的问题。有任何想法吗?

谢谢!

4

6 回答 6

5

联合所有 - 仅选择您要通过的列 - 删除任何其他列。

我认为他们将在 2008 版本中解决这个问题,以允许从管道中修剪/抑制列。

于 2008-11-05T21:42:10.517 回答
2

好的,我在MSDN 论坛上找到了解决方法:

在任务 1 和 2 之间使用脚本组件转换;选择所有输入列;将脚本主体留空。

这会消耗列,作业处理正确,并且不会记录任何警告。

仍然不清楚为什么我需要 OLEDB 源,因为任务 2 中的 SQL 连接到源表并完成所有工作,但是当我删除 OLEDB 源时,数据流运行但不处理任何行,所以暂存表永远不会被清空,然后将更改的行放入临时表的下游进程由于 PK 违规而失败。但这是另一天的问题。这有点笨拙,但我的日志很干净。

于 2008-11-06T00:57:05.240 回答
1

管道中的警告是由在数据源中选择的列未在任何后续任务中使用引起的。

解决此问题的简单方法是双击您的数据源。在您的情况下(OLEDB 源任务:| | 阅读暂存表)然后单击列并取消选择您在将来的任何任务项中不需要的任何列。

这将从您的进度日志中删除这些警告。

但是,阅读您上面的项目并如其他答案所解释的那样,您没有在后续项目中使用源任务中的列,因此可以简单地将其删除。

于 2008-11-27T07:17:51.917 回答
1

我也有同样的问题。我收到了很好的答复。你可以在这里找到它。

正如“ Mark Wojciechowicz ”所说:

以下是一些降低复杂性的建议,这反过来又会提高性能:

  • 在源头减少列。 如果您选择的列随后不会以任何方式使用,请从查询中删除它们或从源组件中取消选中它们。以这种方式删除列会将它们从缓冲区中删除,这将占用更少的内存。
  • 减少数据流中的组件数量。很长的数据流很容易创建,测试起来很痛苦,甚至更难维护。数据流需要一个工作单元,即从这里到那里的数据流,中间有一些东西。这就是数据流大放异彩的地方,事实上,它们通过内存限制和最大线程数来保护自己免受复杂性的影响。最好将工作划分为单独的数据流或存储过程。例如,您可以将数据暂存到一个表中并读取两次,而不是使用多播。
  • 使用数据库。 SSIS 既是一种编排工具,也是一种数据移动工具。我经常发现,使用简单的数据流来暂存数据,然后调用存储过程来处理数据,总是胜过一体化数据流。
  • 增加写入数据的次数。这完全违反直觉,但如果您在较小的操作集中处理数据,则运行速度更快且更易于测试。给定一个干净的状态,我通常会设计一个 ETL 来将数据从源写入临时表,执行从临时表到另一个表的清理步骤,可选地,添加一个一致的步骤以将来自不同源的数据组合到另一个表和,最后,加载目标表的最后一步。请注意,每个源都被推送到其自己的目标表,然后利用数据库进行组合。第一步和最后一步设置为快速运行并避免两端锁定或阻塞。
  • 批量加载。当您确保正在进行批量加载时,上一步确实做得很好。这可能是一件棘手的事情,但通常您可以通过在 OLEDB 目标中使用“快速加载”而不使用 oledb 命令来实现。删除索引并重新添加它们比就地加载要快(很少有例外)。
于 2017-04-13T22:38:08.007 回答
0

再次查看您的问题,我认为您正在“违背原则”使用 SSIS。我并没有真正关注您从临时表中读取的内容,因为您的 upsert 似乎不依赖于特定行中的任何内容,清理也不依赖于任何内容。

在我看来,清理会为每一行运行一次,但这并没有真正的意义。

DataFlows 通常不用于对管道中的每一行执行批量操作。如果您使用的是管道 UPSERT,则使用 Lookup(或第三方 TableDifference)组件处理,然后管道中的 spli 到 OLEDB 目标(BULK INSERT)和 OLEDB 命令(每次更新一次)或另一个 OLDEB 目标“更新临时表”。

通常,我会使用 DataFlow 来加载暂存表而不进行任何拆分,然后在控制流中执行单个 Execute SQL 任务,通过调用 SP 以直接 SQL UPSERT(就像您拥有的那样)执行所有其他操作。

如果您不想拥有临时表,而是读取平面文件并希望使用 Lookup 组件或其他东西执行 UPDATE 或 INSERT,则 OLEDBCommand 很有用。但是它将为管道中的每一行调用。

于 2008-11-07T22:08:40.963 回答
0

DataFlow Task应该以“upsert”结束。然后回到控制流中,为从暂存中删除创建一个Execute SQL Task。将您链接DataFlow Task到您的 exec sql。

我没有为我的 upserts 使用 3rd 方工具,而是按照 Cade 的建议进行操作,即将您的数据流拆分为仅指向 a OLE DB Destination(或类似)的新记录,并更新可以转到您的 oledb 命令进行更新的记录. 您可以使用合并连接或查找来拆分流。

于 2008-11-20T18:41:08.903 回答