2012-03-22 10 views
3

私は、画面上のユーザーアクションによって、新しいレコードが約50の異なるテーブルにリアルタイムで作成されるというシナリオを持っています。ユースケースの設計は、ユーザーアクションの結果として作成された新しいレコードが、ユーザーが変更を行うとすぐに必要となるようなものです。したがって、オフラインまたは遅延創造の可能性はありません。SQL Server - 挿入が多い長いトランザクションのパフォーマンスを向上させるためのより良い方法はありますか?

明らかな問題点は、挿入文(いくつかの追加の操作文とともに)がトランザクション内にあることであり、実際には非常に長いトランザクションになります。これは約30秒間実行され、タイムアウトが発生したり、他のクエリがブロックされることがあります。

アトミック性にはトランザクションが必要です。トランザクションを分割して一貫性を維持するための良い方法はありますか?あるいは現在の状況を改善する他の方法?

+0

50個のテーブルでわずか数百レコードの30秒ですか?それは壊滅的に遅いでしょう。実行計画を調べ、統計を更新し、いくつかのインデックスを追加したり、クエリを書き換えて数分の1にします。 –

+0

プライマリテーブルのインデックスを確認し、もう一度見ていきます。レコードが挿入されるテーブルはすべて、アプリ内の他のいくつかのページで頻繁に使用される「プライマリテーブル」です。主な問題は、挿入クエリが、その時点で同時に実行されている他の(主に選択された)クエリを待っているように見えることです。トランザクションは長いため、1つのテーブルまたは他のテーブルでブロックします。 – Lalman

+0

実行計画にネストされたループがない場合は、他のトラフィックが原因である可能性があります。比較的容易なアクションの1つは、他のトラフィックの中でより遅いクエリを監視し、最悪の犯罪者を最適化するか、プライマリテーブルではなく特殊なインデックス付きビューを使用するように書き直すことです。 –

答えて

4

INSERTクエリは、あなたが別名、row versioned based isolation levelを使用することを検討すべきである はその瞬間

で並列に実行されている他の(主に選択)クエリに待っています。 SNAPSHOT。行バージョン管理の分離レベルでは、読み取りは書き込みをブロックせず、書き込みは読み取りをブロックしません。私はそれでREAD_COMMITTED_SNAPSHOTおよびテストを可能にすることから始めます:

ALTER DATABASE [...] SET READ_COMMITTED_SNAPSHOT ON; 

は、私は、行バージョン管理によって暗黙的意味とトレードオフの説明については、リンク先の記事を読んでお勧めします。

+0

私は確かにいくつかの監視の後にこれを考慮したいと思います。提案していただきありがとうございます。 – Lalman

1

コメント交換に基づいて、私は挿入トランザクションと同時クエリの両方を同時に調べなければならないと思います。トランザクションの整合性を損なうことなく負荷を調整する必要があります。可能な最適化技術が含まれます:あなたが頻繁に見たり、ゆっくりと実行クエリの実行計画での大規模なデータセットを超える(例えば、ネストされたループ)遅い構造に気づくたび

  1. は、アクセスのインデックスを追加します。

  2. カバーリングインデックスの追加。これらのインデックスには、ルックアップ列に加えて追加の列が含まれているため、特定のクエリがテーブルへのトリップをまったく避けることができます。これは、テーブルがワイドでカバーインデックスが狭い場合に特に有効ですが、UPDATEと同じ行の異なるカラムのSELECT間のロックの問題を避けるためにも使用できます。

  3. 非正規化。たとえば、物理テーブルやプライマリテーブルの更新時にトリガを与えられたセカンダリテーブルとは対照的に、クエリの一部を切り替えてインデックス付きビューにアクセスします。これらは高価で重複した技術であり、証明されたトップボトルネックを解決するためにのみ考慮する必要があります。

パフォーマンスの面でこれらの技術が無料で提供されていないため、スピードアップの測定値が非常に大きい変更のみを行います。各ステップでパフォーマンス測定を行わずに最適化しないでください。

これは些細なことですが、完全性について言及しましょう。実行計画を分析している間も、実稼働環境でも統計を最新の状態に保ちます(データベースエンジンごとに、UPDATE STATISTICS、...)。

+1

あなたは正しいですし、私たちはすでに状況を改善した入れ子になったループをもう片付けました。また、50個のテーブルに挿入する特定の「挿入トランザクション」ではなく、各テーブルのすべての列を含むため、多くのインデックス(Coveringインデックスの追加を含む)を他のOLTPトランザクションに変更しました。insert into ... select * from)。私はトリガーから遠ざかりたいが、インデックス付きのビューは今後のパフォーマンステストサイクルで試してみたいことかもしれない。あなたの考えに感謝Jirka、。 – Lalman

関連する問題