如何使用SSIS包导入大型数据集时执行查找?

Jos*_*eph 4 ssis

我有一个问题 - 我希望通过SSIS(Microsoft ETL)下载客户数据.对于我导入的每个客户记录,我必须检查目标数据库中的现有客户记录.如果记录存在,我必须更新记录,如果不存在,我必须插入它.最佳表现策略是什么?我们说的是2000到3000万行.

我想到了触发器(INSERT上的触发器 - 检查是否存在记录),查找,游标,但我确信有更好的方法,可能使用SSIS中的一个数据流转换?

或者,我将其导入临时表然后在本地进行查找是否更好?

小智 16

这是一个可能的选项,您可以应用于将数据加载到目标表中,无论它是否涉及插入/更新.下面给出的示例在3分钟内将包含100万行的文本文件加载到SQL表中.如果SQL表中不存在该记录,则它将被插入到目标表中,否则该记录将被插入到临时表中,然后该表将借助于存储过程来更新目标表.存储过程还将删除可能存在于SQL表中但不存在于平面文件中的任何记录.该示例使用SSIS 2008 R2和SQL Server 2008 R2后端.

分步过程:

  1. 在SQL Server数据库,即创建两个表dbo.ItemInfodbo.Staging." 脚本"部分下提供了创建表查询.这些表的结构显示在屏幕截图#1中.ItemInfo将保存实际数据,Staging表将保存登台数据以比较和更新实际记录.Id这两个表中的列都是自动生成的唯一标识列.IsProcessed表ItemInfo中的列将用于标识和删除不再有效的记录.

  2. 创建一个SSIS包并创建5个变量,如屏幕截图#2所示.我使用.txt扩展名为制表符分隔文件,因此*.txt使用变量FileExtension中的值.FilePath变量将在运行时分配值.FolderLocation变量表示文件的位置.SQLPostLoadSQLPreLoad变量表示在预加载和后加载操作期间使用的存储过程.这些存储过程的脚本在" 脚本"部分下提供.

  3. 创建指向SQL Server数据库的OLE DB连接.创建一个平面文件连接,如屏幕截图#3和#4所示."平面文件连接列"部分包含列级信息.屏幕截图#5显示了列数据预览.

  4. 配置控制流任务,如屏幕截图#6所示.配置任务Pre Load,Post LoadLoop Files如图截图#7 - #10.IsProcessed对于ItemInfo表中的所有行,Pre Load将截断staging表并将flag 设置为false.Post Load将更新更改,并将删除数据库中未在文件中找到的行.请参阅这些任务中使用的存储过程,以了解在这些Execute SQL任务中执行的操作.

  5. 双击Load Items数据流任务并按照屏幕截图#11所示进行配置.Read File是一个配置为使用平面文件连接的平面文件源.Row Count是派生列转换,其配置显示在screenshto#12中.Check Exist是查找转换,其配置显示在屏幕截图#13 - #15中.查找无匹配输出重定向到Destination Split左侧.查找匹配输出重定向到Staging Split左侧.Destination SplitStaging Split具有与屏幕截图#16中所示完全相同的配置.目标和登台表的9个不同目标的原因是为了提高程序包的性能.

  6. 所有目标任务0 - 8都配置为将数据插入表中dbo.ItemInfo,如屏幕截图#17所示.所有登台任务0 - 8都配置为插入数据dbo.Staging,如屏幕截图#18所示.

  7. 在Flat File连接管理器上,将ConnectionString属性设置为使用变量FilePath,如屏幕截图#19所示.这将使包在循环遍历文件夹中的每个文件时使用变量中设置的值.

测试场景:

Test results may vary from machine to machine. 
In this scenario, file was located locally on the machine. 
Files on network might perform slower. 
This is provided just to give you an idea. 
So, please take these results with grain of salt.
Run Code Online (Sandbox Code Playgroud)
  1. 软件包是在64位计算机上运行的,具有Xeon单核CPU 2.5GHz和3.00 GB RAM.

  2. 加载一个平面文件1 million rows.包裹执行约2分47秒.参考截图#20和#21.

  3. 使用" 测试查询"部分下提供的查询来修改数据,以模拟在第二次运行包期间更新,删除和创建新记录.

  4. 1 million rows在数据库中执行以下查询后,加载包含该文件的同一文件.包裹在约1分35秒内执行.参考屏幕截图#22和#23.请注意屏幕截图#22中重定向到目标和登台表的行数.

上面的答案也是提供给Stack Overflow问题的答案的副本.

希望有所帮助.

测试查询: .

--These records will be deleted during next run 
--because item ids won't match with file data.
--(111111 row(s) affected)
UPDATE dbo.ItemInfo SET ItemId = 'DEL_' + ItemId WHERE Id % 9 IN (3)

--These records will be modified to their original item type of 'General'
--because that is the data present in the file.
--(222222 row(s) affected)
UPDATE dbo.ItemInfo SET ItemType = 'Testing' + ItemId WHERE Id % 9 IN (2,6)

--These records will be reloaded into the table from the file.
--(111111 row(s) affected)
DELETE FROM dbo.ItemInfo WHERE Id % 9 IN (5,9)
Run Code Online (Sandbox Code Playgroud)

平面文件连接列 .

Name        InputColumnWidth     DataType          OutputColumnWidth
----------  ----------------     ---------------   -----------------
Id          8                    string [DT_STR]   8
ItemId      11                   string [DT_STR]   11
ItemName    21                   string [DT_STR]   21
ItemType    9                    string [DT_STR]   9
Run Code Online (Sandbox Code Playgroud)

脚本:( 创建表和存储过程) .

CREATE TABLE [dbo].[ItemInfo](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [ItemId] [varchar](255) NOT NULL,
    [ItemName] [varchar](255) NOT NULL,
    [ItemType] [varchar](255) NOT NULL,
    [IsProcessed] [bit] NULL,
    CONSTRAINT [PK_ItemInfo] PRIMARY KEY CLUSTERED ([Id] ASC),
    CONSTRAINT [UK_ItemInfo_ItemId] UNIQUE NONCLUSTERED ([ItemId] ASC)) ON [PRIMARY]
GO

CREATE TABLE [dbo].[Staging](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [ItemId] [varchar](255) NOT NULL,
    [ItemName] [varchar](255) NOT NULL,
    [ItemType] [varchar](255) NOT NULL,
 CONSTRAINT [PK_Staging] PRIMARY KEY CLUSTERED ([Id] ASC)) ON [PRIMARY]
GO

CREATE PROCEDURE [dbo].[PostLoad]
AS
BEGIN
    SET NOCOUNT ON;

    UPDATE      ITM
    SET         ITM.ItemName    = STG.ItemName
            ,   ITM.ItemType    = STG.ItemType 
            ,   ITM.IsProcessed = 1
    FROM        dbo.ItemInfo    ITM
    INNER JOIN  dbo.Staging     STG
    ON          ITM.ItemId      = STG.ItemId;

    DELETE FROM dbo.ItemInfo
    WHERE       IsProcessed = 0;
END
GO

CREATE PROCEDURE [dbo].[PreLoad]
AS
BEGIN
    SET NOCOUNT ON;

    TRUNCATE TABLE dbo.Staging;     

    UPDATE  dbo.ItemInfo 
    SET     IsProcessed = 0;
END
GO
Run Code Online (Sandbox Code Playgroud)

截图#1:

1

截图#2:

2

截图#3:

3

截图#4:

4

截图#5:

五

截图#6:

6

截图#7:

7

截图#8:

8

截图#9:

9

截图#10:

10

截图#11:

11

截图#12:

12

截图#13:

13

截图#14:

14

截图#15:

15

截图#16:

16

截图#17:

17

截图#18:

18

截图#19:

19

截图#20:

20

屏幕截图#21:

21

截图#22:

22

屏幕截图#23:

23