如何修复运行缓慢的SSIS包

时间:2019-04-24 07:30:08

标签: sql sql-server ssis

我正在尝试将一个表中的大量数据从PROD DB插入到Archive DB中的表。表具有相同的架构,存档表具有下垂的索引和“ Identity insert on”。我只需要插入Arh DB /表中不存在的记录。 我在SSIS序列程序包中使用“执行SQL任务”,它的运行速度非常慢(使用20000插入批处理大小)。我在10分钟内插入了20000条记录。仅提及我需要插入48000000条记录。 SQL Server是2016标准edt。 有解决方案吗?

SQL查询是:

SELECT TOP (@InsertBatchSize) s.ID,.....and other columns 
FROM PRODDB.dbo.source_table AS s WITH (NOLOCK) 
    INNER JOIN ArchiveDB.dbo.MissingIDsTable AS t WITH (NOLOCK) 
    ON s.ID = t.ID 
WHERE s.ID not in (SELECT ID 
                   from ArchiveDB..destination_table 
                   WHERE IsUpdated is null ) 

2 个答案:

答案 0 :(得分:0)

任务-数据库之间的数据传输,目标数据库位于SQL 2016服务器上。
我建议采用以下方法:

  1. 在ArchDB表中创建暂存负载。最好在单独的架构中创建它,并使用与原始表相同的名称,仅出于管理和可读性的考虑。
  2. 通过以下步骤创建SSIS包:

    • 在Exec SQL任务中清理必要的登台表
    • 数据流任务-将所有数据从源移动到ArchDB中的登台表。在数据流上-根据ArchDB目标表定义具有完全缓存的Lookup组件;该组件将检查记录在ArchDB中是否存在。只拾取错过的记录。
    • 将数据从Arch DB中的登台表移至目标表,例如

    使用(TABLOCK)选择插入...从

评论:

    Dli中的
  • 查找组件用于过滤掉现有记录。由于在ArchDB目标表上没有任何索引,因此必须使用完全缓存,但会占用大量RAM。
  • INSERT WITH (TABLOCK)收缩用于利用SQL 2016的并行插入功能。
  • 您可以不用暂存表而直接插入目标表。但是,调试会更加困难。

答案 1 :(得分:0)

Execute SQL不适合进行数据传输。它无法批处理数据,也无法对其进行转换。这就是数据流任务的工作。数据流任务允许使用流水线游标读取源数据,并使用批处理批量操作以最少的日志记录将它们写入数据目标。虽然它的速度取决于源查询。慢查询将导致执行缓慢。

这个问题缺少很多信息,例如源数据库和目标数据库中的表模式。我怀疑来自"Identity insert on"的表的ID列是源中的IDENTITY和主键。如果您只关心新记录,则可以编写源查询,该源查询仅自上次执行以来读取数据,例如:

SELECT s.ID,.....and other columns 
FROM PRODDB.dbo.source_table AS s
where ID>@maxId

@maxId是提供给源查询的查询参数。无需批处理,SSIS可以根据数据源,批处理大小的目标设置等来执行此操作。

此查询仅应用于加载 new 数据。要创建初始副本,请使用源查询不过滤任何内容的其他数据流。使用Where ID>-1之类的东西将返回所有数据,但仅在扫描整个索引之后才返回。当我们已经要复制所有数据时,为什么要那个呢?

该ID也应该是 target 表中的主键。这将加快加载参数值的select MAX(ID) from target操作。它还将检测并防止不可避免的重复错误。无论我们多么谨慎,其他人总是会犯错误,从而导致数据重复。

您可以通过在插入之前禁用索引并在导入操作之后重新启用索引来提高导入性能。

那只是检测更改和复制数据的一种方法。另一种技术是在源表中启用Change Tracking并检索自上次作业运行以来修改的行。

您还可以将修改后的数据复制到登台表中,并将那个与目标一起插入INSERT / UPDATE更改。 ID或更改跟踪可用于查找修改后的数据。这样的好处是可以快速释放源代码。