我不是DBA,但我作为IT人员为一家小公司工作。我必须将数据库从登台复制到生产。我已经创建了一个SSIS包来执行此操作,但运行需要数小时。这也不是一个大型数据仓库类型的项目,它是一个非常简单的Upsert
。我假设我是我设计它的薄弱环节。
这是我的程序:
EXECUTE SQL TASK
)Data Flow Task
)OLE DB Source
Conditional Split Transformation
(使用条件:[!]ISNULL(is_new_flag)
)模拟数据流任务几次以更改表/值,但流程是相同的。我已经阅读了几个关于OLE DB组件的更新速度很慢并尝试了一些但却没有让它快速运行的事情。
我不确定要提供的其他细节,但我可以提供任何要求的内容。
答案 0 :(得分:11)
以下是用 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
中插入约140万行,其中包含RowNumber
列中的唯一值。 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
读取数据/ p>
Lookup transformation
用于检查表格中是否已存在RowNumber值 dbo.DestinationTable
如果记录不存在,则会将其重定向到名为 OLE DB Destination
的 Insert into destination table
,将行插入 dbo.DestinationTable
如果记录存在,它将被重定向到名为 OLE DB Destination
的 Insert into staging table
,将行插入 dbo.StagingTable
。登台表中的这些数据将在第二个“执行SQL任务”中用于执行批量更新。
要为OLE DB Source激活更多行,我运行以下查询以激活一些记录
UPDATE dbo.SourceTable
SET IsActive = 1
WHERE (RowNumber % 9 = 1)
OR (RowNumber % 9 = 2)
首次执行包的方式如下所示。所有行都被定向到目标表,因为它是空的。在我的机器上执行包大概花了3 seconds
。
再次执行行计数查询以查找所有三个表中的行计数。
要为OLE DB Source激活更多行,我运行以下查询以激活一些记录
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任务中使用登台表更新了数据。
再次执行行计数查询以查找所有三个表中的行计数。
我希望能让您了解如何实施解决方案。
答案 1 :(得分:8)
我要看的两件事是你的插页(确保你使用“表格或视图 - 快速加载”或“表名或视图名称变量 - 快速加载”)和您的更新。
正如您已经正确确定的那样,更新逻辑通常是性能下降的原因,这是由于OLE DB组件为流经它的每一行触发单例更新。人们采取的通常做法是将所有更新写入临时表,就像插入逻辑一样。然后使用Data Flow Task
跟进Execute SQL Task
,以执行批量更新。
如果您想获得第三方工具,PragmaticWorks会提供Upsert destination