web-dev-qa-db-ja.com

どちらがより効率的ですか:リンクサーバーから選択するか、リンクサーバーに挿入しますか?

あるサーバーから別のサーバーに(リンクサーバーを介して)データをエクスポートする必要があるとします。より効率的なステートメントはどれですか?

ソースサーバーで実行中:

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です。

32

あるサーバーから別のサーバーにデータをエクスポートする必要があるとします。

使うのが一番

  • すべてのデータがバックアップ/復元を使用したい場合; 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データと呼ばれます。これは高価な操作になります。

---ターゲットサーバーで実行中

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

送信先サーバーでクエリを実行し、送信元サーバーからデータをプルするため、これはデータのプルと呼ばれます。これは、前のものに比べてはるかに高速でリソース消費が少なくなります(プルされるデータの量によって異なります)。

プルメソッドの場合、SQLプロファイラーを使用すると、リンクサーバー(ソースサーバー)全体で単一のSQLステートメントが実行され、結果セットがソースサーバーから宛先サーバーにプルされます。これは、プッシュよりもパフォーマンスが大幅に向上します。方法。

注意すべきもう一つの点は:

リンクサーバー(servername.databasename.schema.tablename a.k.a分散クエリを使用する4つの部分の命名規則)とOPENQUERYの間では、一般にOPENQUERYが高速になります。なぜですか?

リンクサーバーの場合-クエリオプティマイザーは、クエリの用語を調べて実行プランを作成し、リモートクエリとローカルクエリに分割します。ローカルクエリはローカルで実行され、リモートクエリのデータはリモートサーバーから収集され、ローカルでスクラブされ、結合されて単一のレコードセットとしてエンドユーザーに提示されます。

OPENQUERYの場合-指定されたリンクサーバーで指定されたパススルークエリを実行します。 SQL Serverはパススルークエリを未解釈のクエリ文字列としてOLE DBデータソース)に送信します。したがって、SQLはクエリにいかなる種類のロジックも適用せず、推定を試みませんそのクエリが行うことは、指定されたクエリをそのままターゲットのリンクサーバーに渡すだけです。オープンクエリは、1つのクエリで複数のサーバーを参照していない場合に便利です。SQLは複数の操作に分割しないため、通常は高速です。受信した出力に対してローカルアクションを実行しません。

優れた参考資料:

29
Kin Shah

効率をどのように測定していますか?どちらが速くなりますか?ターゲット上で消費するリソースが少なくなるのはどれですか?ソースで?これらの行の列はいくつの行とどのようなデータ型ですか?リンクサーバー経由でTVFを実行できますか? (ターゲットSQL 2008以降ですか?) ? TVFから取得する場合、このデータの1:1の移行をどのように保証しますか?

それらの質問は邪魔にならずに...

更新1

ETL(Extract-Transform-Load)を探しているようです。ソースからデータをプルし、必要な変換を適用して、それらをターゲットにロードできる SSIS(SQL Server Integration Services) をお勧めします。これはかなり簡単なパッケージのように思えます(変換によって異なります)。


従来の知識では、リンクサーバーアプローチはリンクに移動し、データをローカルサーバーにプルして、ローカルサーバーにロジック(フィルター、結合など)を適用します。リンクサーバーでデータをフェッチするためのオーバーヘッドが多少ありますが、処理の大部分はローカルで処理されます。

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でテンプレートを使用する方法については この回答 を参照してください。

8
swasheck