SSIS包在一台服务器上运行时间长达500倍

时间:2013-12-16 08:24:49

标签: sql-server sql-server-2008 ssis windows-server-2008 windows-server-2008-r2

我有一个SSIS包 - 两个数据流任务,每个8个组件,从两个平面文件读取,没有什么了不起的。如果我在BIDS中运行它,它需要可靠的大约60秒。我有一个沙箱数据库服务器,其中包在一个作业中运行,也可以在30-60秒内可靠运行。在我的生产服务器上,使用相同程序包的相同作业需要30秒到 12小时

在程序包上启用日志记录后,在一个或另一个(或两个)数据流任务的预执行阶段,它看起来似乎陷入困境 - 最初至少是这样。但是我也可以看到数据进入 - 慢慢地,以块为单位,所以我认为它确实会从那里开始。 IO子系统受到攻击,SSIS会生成许多大型临时文件(价值约150MB - 我的输入数据文件只有大约24MB),并且正在从这些文件中进行大量读写(捶打?)。

值得注意的是,如果我将包的BIDS实例指向生产服务器,它仍然只需要大约60秒就可以运行!所以它必须是那里运行dtexec的东西,而不是DB本身。

我已经尝试优化我的包,减少输入行字节大小,并且我使两个数据流任务串行运行而不是并行运行 - 无济于事。

两个数据库服务器都运行MSSQL 2008 R2 64位,相同的补丁级别。两台服务器都是同一主机上的虚拟机,具有相同的资源分配。生产服务器上的负载不应该比沙盒服务器上的负载高得多。我能看到的唯一区别是生产服务器正在运行 Windows Server 2008,而沙箱位于Windows Server 2008 R2 上。

帮助!!!任何想尝试的想法都是受欢迎的,可能导致这种巨大的差异?

附录A

这是我的包裹的样子......

控制流程非常简单:

Control Flow

数据流如下所示:

Data Flow

第二个数据流任务完全相同,只是使用不同的源文件和目标表。

备注

控制流中的完成约束只是使任务串行运行以尝试并同时减少所需的资源(而不是它有助于解决问题)......两个任务之间没有实际的依赖关系。

我知道阻塞和部分阻塞转换的潜在问题(不能说我完全理解它们,但至少有些),我知道聚合和合并连接是阻塞的,可能会导致问题。然而,再一次,除了生产服务器之外,所有其他环境中的这一切都运行良好且快速...所以给出了什么?

合并加入的原因是使任务等待多播的两个分支完成。右分支在输入中找到最小日期时间并在该日期之后删除表中的所有记录,而左分支携带新的输入记录以进行插入 - 因此如果右分支在聚合和删除之前进行,则新记录将被删除(发生这种情况)。我不知道有更好的方法来管理它。

“删除记录”中的错误输出始终为空 - 这是故意的,因为我实际上并不希望合并中来自该分支的任何行(合并仅用于同步完成,如上所述)。 / p>

请参阅下面有关警告图标的评论。

2 个答案:

答案 0 :(得分:4)

如果您已启用日志记录,最好是SQL Server,请添加OnPipelineRowsSent事件。然后,您可以确定它在哪里花费所有时间。请参阅此post您的IO子系统受到猛烈攻击并生成所有这些临时文件是因为您无法再将所有信息保存在内存中(由于您的异步转换)。

链接文章的相关查询如下。它查看sysdtslog90中的事件(SQL Server 2008+用户替换sysssislog)并对它们执行一些时间分析。

;
WITH PACKAGE_START AS
(
    SELECT DISTINCT
        Source
    ,   ExecutionID
    ,   Row_Number() Over (Order By StartTime) As RunNumber
    FROM
        dbo.sysdtslog90 AS L
    WHERE
        L.event = 'PackageStart'
)
, EVENTS AS
(
    SELECT
        SourceID
    ,   ExecutionID
    ,   StartTime
    ,   EndTime
    ,   Left(SubString(message, CharIndex(':', message, CharIndex(':', message, CharIndex(':', message, CharIndex(':', message, 56) + 1) + 1) + 1) + 2, Len(message)), CharIndex(':', SubString(message, CharIndex(':', message, CharIndex(':', message, CharIndex(':', message, CharIndex(':', message, 56) + 1) + 1) + 1) + 2, Len(message)) ) - 2) As DataFlowSource
    ,   Cast(Right(message, CharIndex(':', Reverse(message)) - 2) As int) As RecordCount
    FROM
        dbo.sysdtslog90 AS L
    WHERE
        L.event = 'OnPipelineRowsSent'
)
, FANCY_EVENTS AS
(
    SELECT
        SourceID
    ,   ExecutionID
    ,   DataFlowSource
    ,   Sum(RecordCount) RecordCount
    ,   Min(StartTime) StartTime
    ,   (
            Cast(Sum(RecordCount) as real) /
            Case
                When DateDiff(ms, Min(StartTime), Max(EndTime)) = 0
                    Then 1
                Else DateDiff(ms, Min(StartTime), Max(EndTime))
            End
        ) * 1000 As RecordsPerSec
    FROM
        EVENTS DF_Events
    GROUP BY
        SourceID
    ,   ExecutionID
    ,   DataFlowSource
)
SELECT
    'Run ' + Cast(RunNumber As varchar) As RunName
,   S.Source
,   DF.DataFlowSource
,   DF.RecordCount
,   DF.RecordsPerSec
,   Min(S.StartTime) StartTime
,   Max(S.EndTime) EndTime
,   DateDiff(ms, Min(S.StartTime)
,   Max(S.EndTime)) Duration
FROM
    dbo.sysdtslog90 AS S
    INNER JOIN
        PACKAGE_START P
        ON S.ExecutionID = P.ExecutionID
    LEFT OUTER JOIN
        FANCY_EVENTS DF
        ON S.SourceID = DF.SourceID
        AND S.ExecutionID = DF.ExecutionID
WHERE
    S.message <> 'Validating'
GROUP BY
    RunNumber
,   S.Source
,   DataFlowSource
,   RecordCount
,   DF.StartTime
,   RecordsPerSec
,   Case When S.Source = P.Source Then 1 Else 0 End
ORDER BY
    RunNumber
,   Case When S.Source = P.Source Then 1 Else 0 End Desc

,DF.StartTime ,Min(S.StartTime);

您可以使用此查询来识别合并连接组件是滞后组件。为什么它在两台服务器之间的表现不同,我现在不能说。

如果您能够在目标系统中创建表,则可以将流程修改为具有两个2数据流(并消除昂贵的异步组件)。

  1. 第一个数据流将采用Flat文件和Derived列,并将其放入临时表中。
  2. 然后启动执行SQL任务以处理获取最小日期+删除逻辑。
  3. 然后,您的第二个数据流将从您的临时表中查询并将其直接捕捉到您的目的地。

答案 1 :(得分:-1)

以下步骤有助于提高您的SSIS效果。