6


3

SQL 2005-リンクされたサーバーからOracleクエリへの非常に遅い

SQL 2005サーバーには、OraOLEDB.Oracleプロバイダーを介してOracleに接続するリンクサーバーがあります。

次のように4つの部分からなる識別子でクエリを実行すると:

SELECT * FROM [SERVER]...[TABLE] WHERE COLUMN = 12345

完了するには1分以上かかります。 同じクエリを次のように実行すると:

SELECT * FROM OPENQUERY(SERVER, 'SELECT * FROM TABLE WHERE COLUMN = 12345')

すぐに完了します。 かなりの期間で最初のクエリを実行するためにどこかに欠けている設定はありますか? または、openqueryを使用して立ち往生していますか?

1 Answer


10


「ドット」表記を使用する最初の例では、クライアントカーソルエンジンが使用され、ほとんどのことはローカルで評価されます。 大きなテーブルから選択してWHERE句を使用している場合、レコードはリモートデータベースからローカルにプルダウンされます。 データがリンクサーバーに渡されると、WHERE句がローカルに適用されます。 多くの場合、このシーケンスはパフォーマンスに影響します。 リモートDBのインデックスは基本的に役に立たなくなります。

または、OPENQUERYを使用すると、SQL Serverは処理のためにsqlステートメントをターゲットデータベースに送信します。 処理中、テーブルのインデックスが活用されます。 また、結果セットをSQL Serverに送り返す前に、Oracle側でwhere句が適用されます。

私の経験では、最も単純なクエリを除き、OPENQUERYを使用するとパフォーマンスが向上します。

上記の理由から、すべてにOpenQueryを使用することをお勧めします。

OpenQueryを使用する際の問題の1つは、既に発生している可能性があるため、単一引用符です。 リモートデータベースに送信されるSQL文字列が文字列または日付を囲む単一引用符を必要とする場合は、エスケープする必要があります。 それ以外の場合は、誤ってsql文字列を終了します。

これは、リンクサーバーへのopenqueryステートメントの変数を処理して、単一引用符の問題を処理するときに使用するテンプレートです。

DECLARE @UniqueId int
, @sql varchar(500)
, @linkedserver varchar(30)
, @statement varchar(600)

SET @UniqueId = 2

SET @linkedserver = 'LINKSERV'
SET @sql = 'SELECT DummyFunction(''''' + CAST(@UniqueId AS VARCHAR(10))+ ''''') FROM DUAL'
SET @statement = 'SELECT * FROM OPENQUERY(' + @linkedserver + ', '
SET @Statement = @Statement + '''' +  @SQL + ''')'
EXEC(@Statement)