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

时间:2012-07-20 06:36:21

标签: sql-server-2008 ssis

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

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

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

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

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

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

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

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

我已经多次在网上搜索过,感谢Google和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

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

----------------------
|  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       |
----------------------

1 个答案:

答案 0 :(得分:2)

我们采取一些措施:

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

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

  2. 建议:假设上述模式在第10,000个插入中成立(请告知是否不同),我最好的猜测是发生了一些阻塞,可能类似于约束验证这是一个嵌套的循环连接,它会像你看到的那样以对数方式与表中的行数进行对比。请你做以下事情:

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