将包含大量记录的表导出到链接服务器上的另一个数据库

时间:2015-09-08 13:35:31

标签: sql ssis sql-insert linked-server

我在一个项目中有一个任务,需要一个进程的结果,可以是1000到10,000,000条记录(大约上限),在一个链接的另一个数据库中插入到具有相同结构的表中服务器。要求是能够以块的形式传输以避免任何超时

在进行一些测试时,我设置了一个链接服务器,并使用以下代码测试转移的约18000条记录:

DECLARE @BatchSize INT = 1000

WHILE 1 = 1
BEGIN

INSERT INTO [LINKEDSERVERNAME].[DBNAME2].[dbo].[TABLENAME2] WITH (TABLOCK)  
(
    id
    ,title
    ,Initials
    ,[Last Name]
    ,[Address1]
)
SELECT TOP(@BatchSize) 
    s.id
    ,s.title
    ,s.Initials
    ,s.[Last Name]
    ,s.[Address1]
FROM [DBNAME1].[dbo].[TABLENAME1] s
WHERE NOT EXISTS ( 
    SELECT 1
    FROM [LINKEDSERVERNAME].[DBNAME2].[dbo].[TABLENAME2]
    WHERE id = s.id
)

IF @@ROWCOUNT < @BatchSize BREAK

这很好但是花了5分钟来传输数据。

我想使用SSIS实现这一点,并且正在寻找有关如何执行此操作并加快流程的任何建议。

1 个答案:

答案 0 :(得分:1)

打开Visual Studio / Business Intelligence Designer Studio(BIDS)/ SQL Server数据工具-BI版(SSDT)

在“模板”选项卡下,选择“商业智能”,“Integration Services项目”。为其指定一个有效名称,然后单击“确定”。

在默认打开的Package.dtsx中,在Connection Managers部分中,右键单击 - &#34; New OLE DB Connection&#34;。在“配置OLE DB连接管理器”部分中,单击&#34;新建...&#34;然后为源数据选择服务器和数据库。单击“确定”,“确定”。

重复上述过程,但将其用于目标服务器(链接服务器)。

将上述连接管理器从server\instance.databasename重命名为更好的内容。如果databasename在环境中没有变化,那么只需使用数据库名称即可。否则,请使用它的通用名称。 即。如果它是SLSDEVDB - &gt; SLSTESTDB - &gt;在您的环境中迁移时SLSPRODDB,请将其设为SLSDB。否则,最终会有人谈论连接管理器,其名称为&#34; sales dev database&#34;但它实际上指的是生产。

向您的包中添加数据流。称之为数据流任务之外的有用的东西。 DFT Load Table2将是我的偏好,但您的里程可能会有所不同。

双击数据流任务。在这里,您将添加OLE DB源,查找任务和OLE DB目标。可能一如既往,它将取决于。

OLE DB Source - 使用我们定义的第一个连接管理器和查询

SELECT 
    s.id
    ,s.title
    ,s.Initials
    ,s.[Last Name]
    ,s.[Address1]
FROM [dbo].[TABLENAME1] s

只需拉入您需要的列。您的查询当前过滤掉目标中已存在的所有重复项。这样做可能很有挑战性。相反,我们将整个TABLENAME1带入管道并过滤掉我们不需要的东西。对于源表中的大量卷,这可能是一种站不住脚的方法,我们需要做不同的

从Source我们需要使用Lookup Transformation。这将允许我们检测重复项。使用我们定义的第二个连接管理器,一个指向目标的连接管理器。更改NoMatch来自&#34;失败组件&#34;到&#34;重定向不匹配的行&#34; (名称近似)

使用您的查询撤回键值

SELECT T2.id
FROM [dbo].[TABLENAME2] AS T2;

将T2.id映射到id列。

当包启动时,它将针对目标表发出上述查询,并将T2.id的所有值缓存到内存中。由于这只是一个列,这不应该太昂贵,但对于非常大的表,这种方法可能不起作用。

Lookup现在有3个输出:Match,NoMatch和Error。 Match将是源和目标中存在的任何内容。你不关心那些,因为你只对源中存在而不是目的地感兴趣。当您需要关心的是,您是否必须确定源和目标中的值之间是否存在更改。 NoMatch是源中存在但不存在于Destination中的行。这就是你想要的流。为了完整起见,Error会抓住那些非常错误但却没有经历过的事情#34;在野外&#34;查找。

将NoMatch流连接到OLE DB目标。在那里选择您的表名称,确保快速加载字样在目的地中。单击“列”选项卡,确保所有内容都已布线。

是否需要摆弄OLE DB目标上的旋钮是高度可变的。我会测试它,特别是使用更大的数据集并查看超时条件是否是一个因素。

较大集合的设计注意事项

取决于。

真的,确实如此。但是,我会考虑确定痛点所在。

如果我的源表非常大并且将所有数据都拉到管道中只是为了将其过滤掉,那么我会看一下像数据流这样的东西,首先将我的Lookup中的所有行都带到源数据库(使用T2查询)并将其写入临时表,并使一列成为您的聚簇键。然后修改源查询以引用临时表。

根据目标表的活动程度(是否有任何其他进程可以加载它),我可能会在数据流中保留该查找以确保我不加载重复项。如果此进程是唯一加载它的进程,则删除查找。

如果查找有问题 - 它无法提取所有ID,则可以使用上面列出的第一个备用,或者查看将缓存模式从完全更改为部分。请注意,这将向目标系统发出查询,以查找源数据库中可能出现的所有行。

如果目的地提出问题 - 我确定问题所在。如果它是加载数据的网络延迟,请将MaximumCommitInsertSize的值从2147483647删除到合理的值,如上面的批量大小(尽管1k可能有点低)。如果您仍然遇到阻止,那么可能将数据暂存到远程服务器上的另一个表中,然后在本地执行插入可能是一种方法。