首先,一些背景知识,我是 SSIS 新手,我刚刚完成了我的第二个数据导入项目。
该程序包非常简单,包含一个数据流,该数据流将大约 30,000 条记录的制表符分隔的客户值文件导入到 ADO 记录集变量中,该变量又用于为 ForEach 循环容器提供动力,该容器执行一条 SQL,从每个循环中传递值记录集的行。
前约 21,000 条记录的导入需要 59 小时才能完成,然后才失败!最后的约 9,000 个又花了 8 个小时。是的,总共67小时!
SQL 包括确定记录是否已存在的检查、对过程的调用以生成新密码以及对另一个过程的最终调用以将客户数据插入我们的系统。最后的过程返回一个记录集,但我对结果不感兴趣,所以我忽略了它。我不知道 SSIS 是否丢弃记录集。我知道这是将数据输入系统的最慢的方法,但我没想到它会这么慢,也没有在三分之二的过程中失败,在处理最后的 ~9,000 时再次失败。
当我在本地机器上测试约 3,000 条记录子集时,执行包实用程序报告每个插入大约需要 1 秒。快速计算一下,建议运行总导入大约需要 8 小时。看起来很长一段时间,考虑到我读过的关于 SSIS 和 RBAR 执行的所有内容,我已经预料到了。我认为最终导入会更快一些,因为服务器功能要强大得多。虽然我正在远程访问服务器,但我没想到这会成为一个问题,因为我过去曾使用定制的 c# 控制台应用程序执行导入,这些应用程序使用简单的 ADO 连接并且没有任何东西运行得这么慢。
最初目标表没有针对存在检查进行优化,我认为这可能是性能缓慢的原因。我在表中添加了一个适当的索引,以将测试从扫描更改为查找,期望这将摆脱性能问题。奇怪的是它似乎没有明显的效果!
我们使用 sproc 将数据插入系统的原因是为了保持一致性。如果数据通过我们的 Web 前端插入到我们的系统中,它代表的路径相同。数据的插入还会导致许多触发器触发和更新数据库中的各种其他实体。
不过,在此导入期间发生的事情让我摸不着头脑,即执行包实用程序的输出报告的 SQL 批处理的执行时间在运行期间呈对数增长。开始时不到一秒的执行时间,最终在导入过程中超过 20 秒,最终导入包只是完全停止。
感谢 Google 以及 StackOverflow,我在网上搜索了很多次,但没有找到任何描述这些症状的东西。
希望有人在那里提供一些线索。
谢谢
作为对 ErikE 的回应:(我无法将其放入评论中,所以我在这里添加了它。)
埃里克。根据您的要求,我在数据库上运行分析器,同时通过它的速度运行三千个项目测试文件。
我无法轻松弄清楚如何让 SSIS 将可见差异插入到探查器可见的代码中,因此我只是在整个运行过程中运行探查器。我知道这会产生一些开销,但是从理论上讲,它应该在运行过程中或多或少保持一致。
在整个运行过程中,每个项目的持续时间保持不变。
下面是跟踪的裁剪输出。在我在这里完成的运行中,前 800 个重叠的先前输入的数据,所以系统实际上没有做任何工作(耶索引!)。一旦索引不再有用并且系统实际上正在插入新数据,您可以看到时间相应地跳跃,但它们似乎并没有太大变化,如果在第一个和最后一个元素之间,读取次数是最大的项目。
------------------------------------------ | 项目 | 中央处理器 | 阅读 | 写 | 持续时间 | ------------------------------------------ | 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
确定每次执行之间的时间差的结果(为简洁起见裁剪)。
---------------------- | 行 | 增量(毫秒)| ---------------------- | 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 | ----------------------