質問

職場には 2 台のサーバーがあり、1 台は SQL Server 2000 バックエンドを備えた多くの人が使用するアプリケーションを実行しています。長い間これを自由にクエリできましたが、ストアド プロシージャや追加のテーブルなどを追加することはできません。

このため、最初の SQL Server にリンクされた 2 番目の SQL Server を用意し、リンク サーバーを使用して両側からデータをクエリするストアド プロシージャのライブラリを構築することになりました。これらのクエリの中には、予想よりも時間がかかるものもあります。

誰かがリンク サーバーの使用に関する良い記事を教えてくれませんか?通常、SQLステートメントの大部分はリモートで実行できるため、2つの間でどのようなデータが転送されているかを調べることに特に興味がありますが、テーブル全体を転送している可能性があると感じています。通常は小さな最後の結合にすぎませんローカルのテーブル。

また、現在使用しているリンク サーバー オプションは何ですか:

  • 照合順序互換性あり True
  • データアクセス真
  • Rpc True
  • RPC アウト True
  • リモート照合順序を使用する False
  • 照合順序名 (空白)
  • 接続タイムアウト 0
  • クエリタイムアウト0

編集:

この投稿を更新しようと思いました。パフォーマンスを向上させるために、しばらくの間、動的パラメーターを使用して openquery を使用しました。ヒントをありがとう。ただし、これを行うと文字列を処理することになるため、クエリがさらに複雑になる可能性があります。ついにこの夏、SQL Server を 2008 にアップグレードし、ライブ データ ミラーリングを実装しました。正直に言うと、私のタスクではオープン クエリの速度がローカル クエリの速度に近づいていましたが、ミラーリングにより SQL の処理が確実に容易になりました。

役に立ちましたか?

解決

リンクされた結合ではなく、カーソル ループで動的オープンクエリを使用することをお勧めします。これが、MS Access のリンク結合パフォーマンス (少なくとも単一のリモート テーブルの場合) を複製できる唯一の方法です。

ms SQL での通常のリンク結合は、すべてを巨大なテーブルに特別にプルするため、非効率すぎます。

-- カーソル ループ内の openquery の何がそんなに悪いのか知りたいのですが?正しく実行されれば、ロックの問題は発生しません。

他のヒント

リンク サーバー テーブルへの結合は避けてください。

結合に 4 つの部分からなる名前を使用することもできますが、コストが高くなります。結合には、リンク サーバーからのデータ セットを制限し、インデックス付き列を使用するために使用できる基準を含めることができます。

例:

SELECT loc.field1, lnk.field1
FROM MyTable loc
INNER JOIN RemoteServer.Database.Schema.SomeTable lnk
  ON loc.id = lnk.id
  AND lnk.RecordDate = GETDATE()
WHERE loc.SalesDate = GETDATE()

このクエリは、結合が計算される前に、リンク サーバーが使用できる結合の条件も適用します。

推奨される方法は、OPENQUERY の使用です。

OPENQUERY を使用して結合を回避すると、ローカル サーバーは結合用の ID のセットを送信する代わりに、リモートで実行されるクエリのみを送信します。

リンクを使用して一連のデータを取得し、ローカルで計算を実行します。一時テーブル (アドホック クエリ用) を使用するか、夜間ジョブで永続テーブルに行を挿入します。

リモート トランザクション コーディネーターがお気に入りのサーバーに設定されているかどうかによっては、トランザクションの開始が失敗する可能性があります。これを使用すると、より多くのリソースが消費されます。

また、アプリケーションを実行している運用サーバーにアクセスしていることも考慮してください。指定はしていませんが、大量のトランザクションを使用し、挿入と更新を行っていると想定するのが安全だと思います。アプリケーションからリソースを奪うことになります。

あなたの目的はレポート目的でのデータの使用のようです。サーバーを完全なログではなく単純なログを持つように設定すると、効率が向上します。

また、リンク サーバー上のデータの移動によってクエリがキャンセルされることも避けられます。クエリや NOLOCK などのテーブル ヒントに適切な分離レベルを設定することに常に注意してください。

そしてお願いします!決して OPENQUERY (またはリンク サーバー) をループ内に配置しないでください。

このような結合にリンク サーバーを使用する場合は、すぐに接続しているサーバー (「ローカル」) が最も多くのデータを持つサーバーであることが重要です。リンク サーバーはデータのごく一部しか提供しません。それ以外の場合は、はい、結合を実行するために必要なだけのデータを取得します。

代替案には、データのサブセットを一時テーブルにコピーし、結果をスリム化するための作業と、リンク サーバーが実行できる前処理を行ってから、「ローカル」側で結合を実行することが含まれます。

逆の方法で、制御できないサーバーに接続し (リンク サーバーを作成する必要があります)、リンク経由でサーバーに接続することで、簡単にパフォーマンスを向上できることがわかるかもしれません。sproc を作成する必要があるデータを扱う大規模な作業を行う必要がある場合は、データをサーバーにプッシュし、そこで sproc を使用します。

場合によっては、リンク サーバーにこの種の概要の作成を夜間に実行させ、それをローカル サーバーにプッシュし、ローカル サーバーが結合で作業を実行するようにしました。

王室の痛み

以前、当店では複数のサーバーをリンクしていましたが、 そんなピタ.

まず第一に、あなたが説明したのと同様の深刻なパフォーマンスの問題がありました。ネットワーク I/O 統計を見てショックを受けました。あらゆる努力にもかかわらず、SQL Server に適切な動作を促すことができませんでした。

もう 1 つの問題は、ストアド プロシージャのリンク サーバー名がどこにでもハードコーディングされており、オーバーライドする方法がないことです。そのため、開発者は、リンク サーバーに関わる機能を開発サンドボックスで簡単にテストすることができませんでした。これは、汎用的に使用できる単体テスト スイートを作成する上での大きな障害でした。

最終的に、リンク サーバーを完全に廃止し、データ同期を Web サービスに移行しました。

リンク サーバー間でのセミ結合を伴うクエリは、あまり効率的ではない傾向があります。使ったほうがいいかもしれません オープンクエリ データをローカルの一時テーブルに移入し、そこから作業します。

私は数年前に SQL 2000 でリモート リンク サーバー アプリケーションを作成しましたが、あなたが説明したのと同じパフォーマンスの問題に遭遇しました。最高のパフォーマンスを得るために、最終的にストアド プロシージャを何度か書き直すことになりました。

私は一時テーブルを頻繁に使用しました。大量のリモート データを一時テーブルに取得し、それに結合したり、操作したりする方がコストがかからないことがわかりました。あなたが説明したように、ローカルテーブルからリモートテーブルへの結合は非常に遅かったです。

見ている内容の多くは理解できませんでしたが、実行計画の表示と推定実行計画の表示は役立つ傾向がありました。

SQL Server はリンク サーバーに対して通常の最適化を利用できないように見えるため、リモート サーバーでこれらのクエリを実行する効率的な方法が本当にあるのかどうかはわかりません。テーブル全体を転送しているように感じるかもしれませんが、実際にそうなっているのです。

レプリケーション シナリオがうまくいくかどうか疑問に思っています。ローカル サーバーにデータを置くことで、希望どおりに実行される通常のクエリを作成できるようになります。

あなたに紹介できる良い記事を私は知りません。より複雑な SQL Server アプリケーションを作成するにつれて、SQL Server がその下でどのように動作するかをより深く理解する必要があると考えるようになりました。そのために、私たちは職場で Kalen Delaney 編集の MS Press Inside Microsoft SQL Server 2005 シリーズを購入しました。ボリューム1:Storage Engine は間違いなく出発点ですが、私はまだそこまで詳しくは入っていません。最近のいくつかのプロジェクトには SQL Server が関与していないため、SQL Server についての研究が手抜きになってしまいました。

リンク サーバーを使用するのではなく、サーバー上に別のデータベースをセットアップできる可能性はありますか?

これは非常に寛大な問題であり、多くの解決策がある可能性があります。しかし、私たちは非常に多くのユーザーがすべてを試したと言うのを目撃してきました。

私の問題を解決したのは..

SQL Server 2000 を SP2 から SP4 にアップグレードしました。SQL Server 2000 にすでに SP4 がある場合は、Instcat.sql を実行します。私の経験によれば、他のすべての回避策で疲れ果てている場合は、これが確実に機能することを保証できます。

ありがとう、mithalesh mithalesh.gupta@gmail.com

動的 SQL と関数を使用すると、ハードコーディングされた名前の質問を回避できます。たとえば、入力 'cpi.cpi'(目的cpi、サブパスデフォルト)をfurning 'returns' [server-name.domain.lcl、2000]を使用して、関数ufn_linkeddatabase(@purpose nvarchar(255))を使用して実装を試みています。 [CPI] '生産環境(SQL Serverに代替ポート番号を使用する場合、リンクされたサーバー名を含む理由がわかりません)。次に、sqlコマンドが@template varchar(max)に組み立てられ、 @{cpi.cpi}をリンクしたサーバーとデータベースを表し、@workstring = cheplage(@template、n'@ {cpi.cpi} '、。 ..)。関数が実際にデータベース名を取得する方法はプロシージャとは別です。ルックアップ テーブルを使用すると便利です。

問題 - OPENQUERY() を実行すること。少なくとも、リンク サーバー オプションの「照合順序互換性」が「true」に設定されていない限り、より多くのタスクをリンク サーバーで実行できるようにする方が良いでしょう。高速ネットワーク上でも重要です。そして、私たちのサーバールームの内部ネットワークはかなり高速です。OPENQUERY()を実行するには、おそらく「cpi.cpi.server」、「cpi.cpi.database」、および「cpi.cpi.server.database」を個別に処理する必要があります。そして、この設計を使用してアプリケーションを 1 つだけ作成することになる可能性がありますが、その場合は過剰設計になります。ただし、これは、関数自体が特別な作業である必要がないことを意味します。

いずれにせよ、高速ネットワーク ハードウェアを問題に投入するのが、より安価な解決策かもしれません。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top