SSIS ForEach ADO 枚举器 - 性能问题

SSIS ForEach ADO Enumerator - Performance Issues

这是关于使用 ADO Enumerator ForEach 循环的最佳practice/other 方法问题。

我的数据是财务账户,从源系统进入数据仓库。 数据的当前结构是金融交易列表,例如

+-----------------------+----------+-----------+------------+------+
|      AccountGUID      | Increase | Decrease  |    Date    | Tags |
+-----------------------+----------+-----------+------------+------+
| 00000-0000-0000-00000 |        0 |    100.00 | 01-01-2018 | Val1 |
| 00000-0000-0000-00000 |   200.00 |         0 | 03-01-2018 | Val3 |
| 00000-0000-0000-00000 |   400.00 |         0 | 06-01-2018 | Val1 |
| 00000-0000-0000-00000 |        0 |    170.00 | 08-01-2018 | Val1 |
| 00000-0000-0000-00002 |   200.00 |         0 | 04-01-2018 | Val1 |
| 00000-0000-0000-00002 |        0 |    100.00 | 09-01-2018 | Val1 |
+-----------------------+----------+-----------+------------+------+

我的 SSIS 包,当前有两个 forEach 循环

  1. 所有时间余额
  2. 月末余额

所有时间余额

将 AccountGUID 传递到循环中并 selects 该帐户的所有交易。然后它按日期对它们进行排序,第一笔交易是第一笔交易,并为其分配一个序列号。

分配序号后,它开始根据增减cols统计当前余额,以及标签col来计算处理的是哪个余额。

它通过为最新记录分配当前标志来完成此操作。

所有时间平衡 - 工作流程

->Get All Account ID's in Staging table
|-> Write all Account GUID's to object variable
|--> ADO Enumerator ForEach - Loop Account GUID List - Write GUID to variable
|---> (Data Flow) Select all transactions for Account GUID
|----> (Data Flow) Order all transactions by date and assign Sequence number
|-----> (Data Flow) Run each row through a script component transformation to calculate running totals for each record
|------> (Data Flow) Insert balance data into staging table 

月末余额

第二个包 End of Month 做了一些非常相似的事情,除了第二个循环。 select 会查找最早的跨国记录和最新的跨国记录。使用这两个日期,它将计算出这两个日期之间的所有月份并循环每个月份。

在日期循环中,它做几乎相同的事情,根据标签计算余额并为每个帐户标记月末记录。

Issue/Question

目前所有这些都工作正常,但性能很糟糕。

在一个包含大约 8000 个帐户和 500,000 笔交易的数据库中。此过程需要一天以上的时间 运行。这是我们的小客户之一,我为 运行 将其用于我们繁重的数据库的想法感到颤抖。

是否有更好的方法来执行此操作,使用 SQL 游标或其他我没见过的巧妙方法?

好的,所以我已经设法将我的包执行时间从大约 3 天缩短到大约 11 分钟。

我 运行 分析器和标准 windows 统计数据,同时 运行 循环并发现了一些有趣的东西。

首先,在执行包期间几乎没有使用 HDD、CPU、RAM 或网络。它告诉我我已经知道的事情,它并没有尽可能快地 运行ning。

我确实注意到,在每次循环执行之间,在下一个循环实例开始执行之前有 1 到 2 毫秒的延迟。

最终我发现每次循环的新实例开始时,SSIS 都会创建一个到 SQL 数据库的新连接,这似乎是 SSIS 的默认行为。无论何时创建 Source 或 Destination,都会给项目添加连接延迟。

修复:

现在这是一个奇怪的修复,你需要进入你的连接管理器(奇怪的一点)它必须是屏幕上的 window 而不是右侧的项目管理器 window.

如果您 select 在循环中引用的连接,右侧的属性 window(无论如何在我的布局中)您将看到名为 "RetainSameConnection" 的选项默认设置为 false。

通过将其设置为 true,我消除了 2 毫秒的延迟。

考虑因素:

在这样做的过程中,我制造了一堆其他问题,这些问题实际上只是突出了我的包裹中我没有考虑周全的地方。

一些似乎受此更改影响的东西是使用临时 tables 的存储过程,这些似乎立即中断。我假设这是因为 SQL 处理临时 table 的方式,在关闭连接并重新打开时,您可以非常确定临时 table 已经消失。使用相同的连接设置,运行进入临时 tables 的机会似乎再次成为问题。

我删除了所有临时 tables 并用 CTE 语句替换它们,这似乎解决了这个问题。

我发现的第二个主要问题是 运行 并行且都使用相同连接管理器的任务。由此我收到一条错误消息,即 SQL 仍在尝试 运行 之前的语句。这炸毁了我的包裹。

为了解决这个问题,我创建了一个重复的连接管理器(我为同一个数据库创建了三个连接管理器)。

建立连接后,我进入了每个并行的源和目标,并为它们分配了自己的连接管理器。这似乎解决了我收到的最后一个错误。

结论:

这样做可能会有更多无法预料的问题,但目前我的包裹正在​​迅速减轻,这突出了我设计中的一些错误。