5

次のように、いくつかの ID を一時テーブルに挿入して#Aいます。

SELECT DISTINCT ID
INTO #A
FROM LocalDB.dbo.LocalTable1
WHERE ID NOT IN (SELECT DISTINCT ID FROM LocalDB.dbo.LocalTable2)
GO

CREATE INDEX TT ON #A(ID)
GO

前の段階で収集した識別子を使用して、リモートのリンク サーバーから情報を取得しようとしています。

クエリ 1:

SELECT ID, Desc
FROM RemoteLinkedServer.DB.dbo.RemoteTable X
WHERE ID IN (SELECT ID FROM #A)

クエリ 2:

SELECT ID, Desc
FROM RemoteLinkedServer.DB.dbo.RemoteTable X
INNER JOIN #A Y
ON X.ID = Y.ID

次のクエリでは、一時テーブルの出力を取得し、行をコピーしてカンマ区切りのリストに適切にフォーマットし、手動でクエリに入れています。

クエリ 3:

SELECT ID, Desc
FROM RemoteLinkedServer.DB.dbo.RemoteTable X
WHERE ID IN (-- Put all identifiers here --)

クエリ12実行に 2 時間かかり、クエリ3にかかる時間は 0 秒です (一時テーブルには約 200 行が含まれています)。何が起こっているのかわかりませんし、リモート サーバーが ID に関連するインデックスを持っているかどうかを確認する権限もありませんが、手動で作成されたクエリがすぐに実行され、問題が発生していることを示していることを確認するのは単純に困惑しています。クエリ最適化フェーズで。

ここで何がうまくいかないのか、またはクエリを高速化する方法についてのアイデアはありますか?

4

2 に答える 2

10

クエリ 1 と 2 により、結合操作を実行するために、RemoteTable 内のすべてのデータがローカル データベースに取り込まれます。これにより、RAM とネットワーク帯域幅が消費され、クエリの実行中は通常非常に遅くなります。

クエリ 3 により、リモート サーバーは結果をフィルタリングして、必要な一致のみを送信できます。

基本的には、誰がその仕事をするかということになります。クエリ 1/2 では、ローカル DB がそれを行う必要があります。クエリ 3 により、リモート クエリが実行されます。

そのリモート テーブルに大量のデータがある場合、ネットワークの輻輳などが発生する可能性があります。

リンク サーバーにクエリを実行する最善の方法は、リモート サーバーがすべての作業を行い、ローカル サーバーに結果を返すようにクエリを作成することです。これにより、必要なデータを取得するために必要なネットワーク、メモリ、およびディスク リソースの量が最適化されます。

サーバーの境界を越えて (リンクされたサーバーを使用して) 参加する必要があるときはいつでも、災害になるでしょう。

于 2012-08-11T00:40:44.447 に答える
3

参考までに、@ChrisLivelyの提案に基づいて問題を解決した方法は次のとおりです。

SELECT DISTINCT ID
INTO #A
FROM LocalDB.dbo.LocalTable1
WHERE ID NOT IN (SELECT DISTINCT ID FROM LocalDB.dbo.LocalTable2)
GO

CREATE INDEX TT ON #A(ID)
GO

DECLARE @IDList VARCHAR(MAX)
SELECT @IDList=(SELECT TOP 1 REPLACE(RTRIM((
                SELECT DISTINCT CAST(ID AS VARCHAR(MAX)) + ' ' 
                FROM #A AS InnerTable               
                FOR XML PATH (''))),' ',', '))
FROM #A AS OuterResults


DECLARE @sql AS varchar(MAX)
SET @sql = 'SELECT * FROM RemoteLinkedServer.RemoteDB.dbo.RemoteTable X WHERE ID IN (' + @IDList + ')'

EXEC (@sql)

DROP TABLE #A
GO
于 2012-08-11T01:07:11.117 に答える