我不是DBA,但是作为IT人员,我在一家小型公司工作。我必须将数据库从登台复制到生产。我已经创建了一个SSIS包来执行此操作,但是它需要几个小时才能运行。这也不是大型数据仓库类型的项目,它是一个非常简单的Upsert
。我假设我是设计方式中的薄弱环节。
这是我的程序:
EXECUTE SQL TASK
)Data Flow Task
)OLE DB Source
Conditional Split Transformation
(使用的条件:[!]ISNULL(is_new_flag)
)数据流任务被模仿了几次以更改表/值,但是流是相同的。我已经阅读了有关OLE DB组件更新缓慢的一些内容,并尝试了一些方法,但是还没有使其运行得非常快。
我不确定要提供什么其他详细信息,但是我可以提供要求的任何内容。
最佳答案
使用SSIS 2008 R2的示例软件包,可使用批处理操作插入或更新:
这是一个用SSIS 2008 R2
编写的示例程序包,该程序包说明了如何使用批处理操作在两个数据库之间执行插入,更新。
OLE DB Command
会减慢您软件包上的更新操作,因为它不执行批处理操作。每行都单独更新。 该示例使用两个数据库
Source
和Destination
。在我的示例中,两个数据库都驻留在服务器上,但是该逻辑仍然可以应用于驻留在不同服务器和位置上的数据库。我在源数据库
dbo.SourceTable
中创建了一个名为Source
的表。CREATE TABLE [dbo].[SourceTable](
[RowNumber] [bigint] NOT NULL,
[CreatedOn] [datetime] NOT NULL,
[ModifiedOn] [datetime] NOT NULL,
[IsActive] [bit] NULL
)
另外,在目标数据库dbo.DestinationTable
中创建了两个名为dbo.StagingTable
和Destination
的表。CREATE TABLE [dbo].[DestinationTable](
[RowNumber] [bigint] NOT NULL,
[CreatedOn] [datetime] NOT NULL,
[ModifiedOn] [datetime] NOT NULL
)
GO
CREATE TABLE [dbo].[StagingTable](
[RowNumber] [bigint] NOT NULL,
[CreatedOn] [datetime] NOT NULL,
[ModifiedOn] [datetime] NOT NULL
)
GO
在表dbo.SourceTable
中向RowNumber
列中插入了约140万行具有唯一值的行。表dbo.DestinationTable
和dbo.StagingTable
最初是空的。表dbo.SourceTable
中的所有行都将标志 IsActive
设置为false。用两个OLE DB连接管理器创建了一个SSIS包,每个连接器都连接到
Source
和Destination
数据库。设计了控制流程,如下所示:Execute SQL Task
对目标数据库执行语句 TRUNCATE TABLE dbo.StagingTable
,以截断登台表。Data Flow Task
。Execute SQL Task
执行以下给定的SQL语句,该语句使用dbo.DestinationTable
中可用的数据来更新dbo.StagingTable
中的数据,并假定在这两个表之间存在唯一的键。在这种情况下,唯一键是RowNumber
列。脚本更新:
UPDATE D
SET D.CreatedOn = S.CreatedOn
, D.ModifiedOn = S.ModifiedOn
FROM dbo.DestinationTable D
INNER JOIN dbo.StagingTable S
ON D.RowNumber = S.RowNumber
我设计了如下所示的数据流任务。
OLE DB Source
使用SQL命令从dbo.SourceTable
读取数据SELECT RowNumber,CreatedOn, ModifiedOn FROM Source.dbo.SourceTable WHERE IsActive = 1
Lookup transformation
用于检查表dbo.DestinationTable
中是否已存在RowNumber值OLE DB Destination
Insert into destination table
,这会将行插入到dbo.DestinationTable
中OLE DB Destination
Insert into staging table
,它将行插入dbo.StagingTable
中。登台表中的数据将在第二个“执行SQL任务”中使用以执行批处理更新。要为OLE DB源激活更多行,我运行以下查询以激活一些记录
UPDATE dbo.SourceTable
SET IsActive = 1
WHERE (RowNumber % 9 = 1)
OR (RowNumber % 9 = 2)
程序包的第一次执行如下所示。所有行都被定向到目标表,因为它是空的。在我的机器上执行该软件包大约需要
3 seconds
。再次运行行计数查询以查找所有三个表中的行计数。
要为OLE DB源激活更多行,我运行以下查询以激活一些记录
UPDATE dbo.SourceTable
SET IsActive = 1
WHERE (RowNumber % 9 = 3)
OR (RowNumber % 9 = 5)
OR (RowNumber % 9 = 6)
OR (RowNumber % 9 = 7)
程序包的第二次执行如下所示。第一次执行期间先前插入的
314,268 rows
被重定向到登台表。 628,766 new rows
直接插入到目标表中。在我的机器上执行该软件包大约需要12 seconds
。目标表中的314,268 rows
在第二个“执行SQL任务”中已使用登台表中的数据进行了更新。再次运行行计数查询以查找所有三个表中的行计数。
我希望这给您一个实现解决方案的想法。
关于sql-server-2008 - 如何在SSIS包中优化Upsert(更新和插入)操作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14819999/