以对数方式增加ForEach控件的每个循环的执行时间

Asp*_*ont 6 ssis sql-server-2008

首先,一些背景,我是一个SSIS新手,我刚刚完成了我的第二个数据导入项目.

该包非常简单,由一个数据流组成,该数据流将一个约30,000条记录的以制表符分隔的客户值文件导入ADO记录集变量,该变量依次用于为ForEach循环容器提供动力,该容器执行从每个传递值的SQL片段.记录集的一行.

在失败之前,首批~21,000条记录的导入需要59个小时才能完成!最后〜9,000又花了8个小时.是的,总共67个小时!

SQL包括检查以确定记录是否已存在,是否调用过程以生成新密码,以及最后调用另一个过程以将客户数据插入到我们的系统中.最后的过程返回一个记录集,但我在结果中被删除了,所以我忽略了它.我不知道SSIS是否丢弃了记录集.我知道这是将数据输入系统的最慢可能方式,但我没想到它会这么慢,也不会失败三分之二,并且在处理最后的~9,000时再次失败.

当我在本地计算机上测试了~3,000个记录子集时,执行包实用程序报告每个插入大约需要1秒钟.一些快速的数学和建议是总进口需要大约8小时才能运行.似乎很长一段时间,我已经预料到了我读过的关于SSIS和RBAR执行的所有内容.我认为最终导入会更快,因为服务器功能更强大.虽然我正在远程访问服务器,但我不希望这是一个问题,因为我过去已经执行了导入,使用了使用简单ADO连接的定制c#控制台应用程序,并且没有任何东西在任何地方附近运行缓慢.

最初目标表没有针对存在检查进行优化,我认为这可能是性能降低的原因.我在表中添加了一个适当的索引,将测试从扫描更改为搜索,期望这样可以解决性能问题.奇怪的是它似乎没有明显的效果!

我们使用sproc将数据插入系统的原因是为了保持一致性.如果数据通过我们的Web前端插入到我们的系统中,它表示数据所采用的路径.插入数据还会导致许多触发器触发并更新数据库中的各种其他实体.

在导入过程中发生了什么,让我摸不着头脑的是,执行包实用程序的输出所报告的SQL批处理的执行时间在运行期间以对数方式增加.什么开始作为一秒钟的执行时间,在导入过程中以超过20秒结束,最终导入包只是简单地完全停止.

我多次在网上搜索过,感谢谷歌和StackOverflow,并没有发现任何描述这些症状的内容.

希望有人在那里有一些线索.

谢谢

回应ErikE :(我无法将其纳入评论中,所以我在这里添加了它.)

埃里克.根据您的要求,我在数据库上运行了探查器,同时通过它的步伐运行了三千个项目测试文件.

我无法轻易弄清楚如何让SSIS在探查器可见的代码中插入可见的差异,所以我只是为整个运行运行了探查器.我知道会有一些与此相关的开销,但理论上,它应该在运行中或多或少地保持一致.

基于每个项目的持续时间在整个运行期间保持相当恒定.

下面是跟踪的裁剪输出.在我在这里完成的运行中,前800个重叠先前输入的数据,因此系统实际上没有工作(Yay索引!).一旦索引停止有用并且系统实际上插入了新数据,您就可以看到时间相应地跳转,但是如果在第一个和最后一个元素之间,它们似乎没有太大变化,读取次数是最大的项目.

------------------------------------------
| Item | CPU | Reads | Writes | Duration |
------------------------------------------
| 0001 |   0 |    29 |    0   |     0    |
| 0002 |   0 |    32 |    0   |     0    |
| 0003 |   0 |    27 |    0   |     0    |
|…                                       |
| 0799 |   0 |    32 |    0   |     0    |
| 0800 |  78 |  4073 |   40   |   124    |
| 0801 |  32 |  2122 |    4   |    54    |
| 0802 |  46 |  2128 |    8   |   174    |
| 0803 |  46 |  2128 |    8   |   174    |
| 0804 |  47 |  2131 |   15   |   242    |
|…                                       |
| 1400 |  16 |  2156 |    1   |    54    |
| 1401 |  16 |  2167 |    3   |    72    |
| 1402 |  16 |  2153 |    4   |    84    |
|…                                       |
| 2997 |  31 |  2193 |    2   |    72    |
| 2998 |  31 |  2195 |    2   |    48    |
| 2999 |  31 |  2184 |    2   |    35    |
| 3000 |  31 |  2180 |    2   |    53    |
------------------------------------------

一夜之间我还让系统通过完全重新运行导入,打开了探查器,看看事情是怎么回事.它在我的本地机器上设法在15.5小时内完成了导入的三分之一.我将跟踪数据导出到SQL表,以便我可以从中获取一些统计信息.查看跟踪中的数据,插入之间的增量每千个处理记录增加约1秒,因此当它达到记录10,000时,每个记录需要10秒才能执行插入.下面是为每条记录执行的实际代码.不要过分批评这个程序,SQL是由自学成才的开发人员编写的,他早在我公司受雇于实际开发人员教育的人之前就已经是我们的接待员了.我们很清楚它并不好.最重要的是我相信它应该以恒定的速率执行,而且很明显不会.

if not exists
(
    select 1
    from [dbo].[tblSubscriber]
    where strSubscriberEmail = @EmailAddress
    and ProductId = @ProductId
    and strTrialSource = @Source
)
begin
    declare @ThePassword varchar(20)
    select @ThePassword = [dbo].[DefaultPassword]()

    exec [dbo].[MemberLookupTransitionCDS5] 
     @ProductId
    ,@EmailAddress
    ,@ThePassword
    ,NULL --IP Address
    ,NULL --BrowserName
    ,NULL --BrowserVersion
    ,2 --blnUpdate
    ,@FirstName --strFirstName
    ,@Surname --strLastName
    ,@Source --strTrialSource
    ,@Comments --strTrialComments
    ,@Phone --strSubscriberPhone
    ,@TrialType --intTrialType
    ,NULL --Redundant MonitorGroupID
    ,NULL --strTrialFirstPage
    ,NULL --strTrialRefererUrl
    ,30 --intTrialSubscriptionDaysLength
    ,0 --SourceCategoryId
end
GO
Run Code Online (Sandbox Code Playgroud)

确定每次执行之间的时间差异的结果(为简洁而裁剪).

----------------------
|  Row  | Delta (ms) |
----------------------
|   500 |  510       |
|  1000 |  976       |
|  1500 | 1436       |
|  2000 | 1916       |
|  2500 | 2336       |
|  3000 | 2816       |
|  3500 | 3263       |
|  4000 | 3726       |
|  4500 | 4163       |
|  5000 | 4633       |
|  5500 | 5223       |
|  6000 | 5563       |
|  6500 | 6053       |
|  7000 | 6510       |
|  7500 | 6926       |
|  8000 | 7393       |
|  8500 | 7846       |
|  9000 | 8503       |
|  9500 | 8820       |
| 10000 | 9296       |
| 10500 | 9750       |
----------------------

Eri*_*ikE 2

让我们采取一些步骤:

  1. 建议:隔离是服务器问题还是客户端问题。运行跟踪并查看与第 3000 次插入相比第一次插入花费了多长时间。在 SQL 语句中包含第 1 次和第 3000 次迭代的一些差异,可以在跟踪中过滤这些差异,以便它不会捕获其他事件。尽量避免语句完成——使用批处理或 RPC 完成。

    响应:分析器跟踪记录的 CPU、读取和持续时间没有增加,但实际已用/有效插入时间增加。

  2. 建议:假设上述模式在第 10,000 次插入中保持正确(如果不同,请告知),我最好的猜测是发生了一些阻塞,可能类似于正在进行嵌套循环连接的约束验证,这会以对数方式缩放正如您所看到的,表中的行数。请您执行以下操作:

    如果这些都没有在问题上取得进展,只需用任何新信息更新您的问题并在此处发表评论,我将继续尽力提供帮助。