哪一种效率更高:从链接服务器中选择还是插入到链接服务器中?


32

假设我必须将数据从一台服务器导出到另一台(通过链接的服务器)。哪种说法会更有效?

在源服务器中执行:

INSERT INTO [DestinationLinkedServer].[DestinationDB].[dbo].[Table]
SELECT a, b, c, ... FROM [dbo].Udf_GetExportData()

或在目标服务器中执行:

INSERT INTO [dbo].[Table]
SELECT a, b, c, ...
FROM OPENQUERY([OriginLinkedServer],
    'SELECT a, b, c, ... FROM [OriginDB].[dbo].Udf_GetExportData()')

哪一个会更快并且总共消耗更少的资源管理器(源服务器和目标服务器)?两台服务器都是SQL Server 2005。

Answers:


29

假设我必须将数据从一台服务器导出到另一台服务器。

最好是用

  • 如果您希望所有数据都使用备份/还原;BCP OUT和BCP IN或SSIS
  • 如果您想要数据子集(仅某些表),请使用SSIS或BCP OUT和BCP IN

要移动数据,取决于数据量/大小和n / w带宽,链接服务器会降低性能。

在源服务器中执行还是在目标服务器中执行-哪一个会更快并且总共消耗更少的资源服务器(源服务器和目标服务器)?

-在源服务器中执行:

INSERT INTO [DestinationLinkedServer].[DestinationDB].[dbo].[Table]
SELECT a, b, c, ... FROM [dbo].Udf_GetExportData()

当您在源服务器上执行查询并将数据推送到目标服务器时,这称为PUSHING Data。这将是昂贵的操作。

-在目标服务器上执行

INSERT INTO [dbo].[Table]
SELECT a, b, c, ...
FROM OPENQUERY([OriginLinkedServer],
    'SELECT a, b, c, ... FROM [OriginDB].[dbo].Udf_GetExportData()')

在目标服务器上执行查询并从源服务器提取数据时,这称为PULLING Data。与前一个相比,这将更快,更节省资源(取决于要提取的数据量)。

对于pull方法,使用SQL Profiler,您将看到在链接服务器(源服务器)上执行了一条SQL语句,结果集从源服务器转移到了目标服务器,这与PUSH相比具有巨大的性能提升。方法。

要注意的另一点是:

在链接服务器(使用分布式名称的servername.databasename.schema.tablename或别名的4部分命名约定)和OPENQUERY之间,通常OPENQUERY会很快。为什么呢

对于链接服务器 -查询优化器通过查看查询术语来创建执行计划,并将其分为远程和本地查询。本地查询是在本地执行的,而远程查询的数据是从远程服务器收集,本地清理,组合在一起并作为单个记录集呈现给最终用户的。

对于OPENQUERY-在指定的链接服务器上执行指定的传递查询。SQL Server将直通查询作为未解释的查询字符串发送到OLE DB数据源。因此,SQL不会对查询应用任何逻辑,也不会尝试估计该查询将执行的操作,它只会将指定的查询直接传递给目标链接服务器。当您不在一个查询中引用多个服务器时,打开查询很有用。由于SQL不会将其分解为多个操作并且不会对收到的输出执行任何本地操作,因此它通常很快。

优秀的阅读参考书:


8

您如何衡量效率?哪一个会更快?哪一个将消耗较少的目标资源?在源头上?这些行中的列有多少行和什么样的数据类型?您确定可以通过链接服务器执行TVF (目标SQL 2008或更高版本吗?)?如果您是从TVF提取数据,如何确保该数据按1:1迁移?

有了这些问题,...

更新1

听起来您在寻找ETL(Extract-Transform-Load)。我建议使用SSIS(SQL Server集成服务),您可以使用它从源中提取数据,应用所需的转换,然后将其加载到目标中。听起来这将是一个非常简单的程序包(取决于转换)。


传统观点认为,链接服务器方法将使用链接,将数据提取到本地服务器,然后在本地服务器上应用任何逻辑(过滤器,联接等)。在链接服务器上获取数据会有一些开销,但是大部分处理将在本地进行。

OPENQUERY方法将把处理放在远程服务器上,本地服务器将接收“过滤的结果”。

看起来,即使您可以通过链接服务器执行TVF,也会遇到两全其美的情况:远程处理本地处理(假设您需要在集合上应用其他逻辑)。

根据您决定前进的方式,我还将研究OPENQUERY批量导入/导出数据的一种方法。

说了这么多 ...

如果源和目标都在SQL Server上(并且目标不是较低版本),为什么不备份和还原数据?这将是一次真正的数据迁移。这是给您的一些代码。

BACKUP DATABASE <DatabaseName, sysname, DatabaseName>
TO DISK=N'<backup_location, varchar, BackupLocation>.bak'
WITH INIT, FORMAT, COMPRESSION, COPY_ONLY

RESTORE DATABASE <NewDatabaseName, sysname, NewDatabaseName>
FROM DISK = N'<backup_location, varchar, BackupLocation>\
    <DatabaseName, sysname, DatabaseName>.bak'
WITH 
    MOVE '<DataFileName, sysname, DataFileName>' TO '<DataMDFPath, nvarchar(600), DataMDFPath>',
    MOVE '<LogFilePath, sysname, LogFilePath>' TO '<LogLDFPath, nvarchar(600), LogLDFPath>',
    REPLACE;

您可以参考此答案以了解如何在SSMS中使用模板。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.