我需要在客户下订单时将他们的订单与他们的“级别”(白银、黄金等)相关联:
CRM server::CRM db::CRM table
----------
CustomerID PreviousLevel NewLevel NewLevelGrantedOn
Order server::Order db::Order table
----------
OrderID CustomerID OrderPlacedOn
在 SSIS 包中我这样做了:
- 对 Order db 执行 SQL 以提取订单并将它们放入对象变量中;
- 使用“foreach 容器”遍历每个订单,我在其中放置了一个数据流任务,该任务
select top 1 * where CustomerID = ? and LevelGrantedOn < ? order by LevelGrantedOn desc
从 CRM 数据库中提取数据(两个参数都来自第一步),派生一些列并将输出写入另一个表。
订单数据库中有两万多条记录,这意味着数据流任务将被执行两万多次。CRM 数据库也将被查询超过两万次。做这些需要一个多小时。
我可以利用一些内置功能来加速这些(或以“智能”方式进行)吗?而且,在 ETL 和/或 SSIS 的上下文中,一个小时很长吗?
您可以在不使用 Foreach 枚举器的情况下实现这一点,只需使用一个数据流任务即可实现。
构建包
首先,在控制Flow中添加一个Data Flow Task
1.OLEDB 资源
在数据流任务中添加一个
OLEDB Source
从订单表中读取的命令(与Execute SQL Task
(问题的第一步)中使用的命令相同还要添加第二个
OLEDB Source
从客户表中读取的内容:2.排序
在每个 OLEDB Source 之后添加一个源组件:
CustomerID
和OrderID
用于排序的列,并选择排序类型为升序CustomerID
(排序类型=升序)和LevelGrantedOn
(排序类型=降序)列进行排序3.合并加入
添加一个 merge Join 组件来连接两个排序的输出。并
CustomerID
从两个输出中选择列作为 Join Key 并从两个表中选择您需要的输出列4. 有条件拆分
merge Join 后添加条件拆分以仅过滤与以下表达式匹配的行
5.脚本组件
我们必须使用的最后一个组件是一个脚本组件,它只获取每个 customerID 的第一行(因为两个源都排序良好,只是抓取第一行是类似的
Select top 1 ... ORDER BY LevelGrantedOn desc
)在脚本组件
OutFlag
中添加类型的输出列DT_BOOL
并使用以下脚本:当 customerID 第一次出现时,此脚本会将 OutFlag 设置为 True(类似于
TOP 1
)6. 有条件拆分
添加第二个条件拆分以过滤前 1 行:
7.OLEDB目的地
将 Conditional Split Output 连接到 OLEDB Destination 顶部并映射列。
数据流任务必须看起来像
考虑使用 SQL Server 的“Index with included columns”功能,它可以在数据收集过程中加快查询性能。