0

複数のクライアント データベースで、SQL Server 2008 R2 で 1 日に数回実行されている次のクエリがあります。

UPDATE    Propane.RecordKey
With (TabLock)
SET              LookupKey = System.Param_RecordKey.LookupKey
FROM         Propane.RecordKey INNER JOIN 
                  System.Param_RecordKey ON 
                  Propane.RecordKey.IndexId = System.Param_RecordKey.IndexId
                  And Propane.RecordKey.RecordNumber = System.Param_RecordKey.RecordNumber                       
                  AND Propane.RecordKey.LookupKey <> System.Param_RecordKey.LookupKey
WHERE     (System.Param_RecordKey.ParameterKeyId = @key)

このクエリをできるだけ早く実行する方法についての提案を探しています。現在、数秒から 1 分以上の遅延が発生しています。

パフォーマンスは一貫しておらず、多くのレコードが影響を受ける場合は比較的速く実行され、他の場合は影響を受けるレコードが少なく実行が非常に遅くなります。私のテスト マシンでは、パフォーマンスは概ね許容範囲内です (つまり、10,000 件以上のレコードで数秒) が、一部のクライアントでは大幅な遅延が発生しています。

私が説明できないこの極端な変動と、クエリのパフォーマンスを微調整する方法についての限られた知識とが相まって、あまりメリットがなく、クエリの実行が悪化する可能性のある変更を試すのをためらっています。

更新されるテーブル RecordKey は、頻繁に (1 日に数百から数千回) 読み取られ、ときどき (1 日に数回) 更新されます。

RecordKey のプライマリ インデックスは、IndexId と RecordNumber です。Param_RecordKey には、ParameterKeyId、IndexId、および RecordNumber のキー フィールドがあります。つまり、両方のテーブルの主キー フィールドをフィルタリングして結合しています。これらのフィールドはすべて int です。

RecordKey には、数十万から数百万のレコードが含まれます。Param_RecordKey には、更新中のレコードのみが含まれます。通常、Param_RecordKey には数千のレコードが含まれますが、数万のレコードが一般的であり、100,000 以上のレコードが可能です。

両方のテーブルの LookupKey フィールドは varchar(27) です。ほとんどの場合、フィールドに格納されるテキストの長さは 5 ~ 10 文字です。10 ~ 15 文字の長さが一般的で、20 文字を超える長さはまれです。ほとんどの場合、それぞれの LookUpKey の値は同じです。つまり、更新されるレコードはほとんどありません。まれに、すべてのレコードが更新されることがあります。

私が持っている質問の 1 つ: Propane.RecordKey.LookupKey <> System.Param_RecordKey.LookupKey のチェックを削除すると、パフォーマンスが向上しますか? つまり、LookupKey が異なるレコードだけでなく、すべてのレコードを更新する場合です。すべてのレコードを更新する時間は、変更されたレコードを更新するよりも長くなると予想されますが、これが正しいかどうかはわかりません。

このクエリを改善する方法についてアドバイスをいただければ幸いです。


2013 年 4 月 9 日、新しい情報。

With (TabLock) を削除し、クライアントのサイトで変更をテストした後、結果はまちまちです。場合によっては、クエリの実行が大幅に速くなったり、遅くなったりしましたが、多くの場合、レコードの処理にかかる時間に大きな変化はありませんでした。

変更を行っても、パフォーマンスが大幅に改善されたわけではないため、この質問は未回答のままにしておきます。私はまだこの問題の支援に興味があります.

4

3 に答える 3

2

テーブル ヒント TABLOCK は、更新中のテーブルで排他ロックを取得する可能性があります。このようなロックは、共有ロックであっても他のロックと互換性がなく、パフォーマンスに影響を与えます。クエリが排他的なテーブル ロックを必要とする場合、他のロックが取得されなくなるまで待機する必要があります。ヒントを削除して、データベース エンジンにロック戦略を決定させます。これは非常に得意です。テーブルにアクセスするのは (おそらく) 唯一の人であり、他のロックは取得されないため、開発マシンでのパフォーマンスは許容範囲内です。

于 2013-04-05T17:06:28.377 に答える
0

変数を使用したこのようなスクリプトで私が見た中で最も優れた改善点の 1 つは、動的クエリを作成し、変数を sql に変換してから、結果の sql を実行することでした。もちろん、これを行っている間、インデックスが再構築されていることを確認してください(または少なくとも統計が最新の状態になっていることを確認してください)。DBCC TRACEON 2301 および 8780 も役立ちます。

于 2015-05-20T18:11:27.190 に答える
0

2 つの解決策があります。2 番目の解決策は、おそらく現在よりも高速に動作するはずです。

UPDATE    Propane.RecordKey
With (TabLock)
SET              LookupKey = System.Param_RecordKey.LookupKey
FROM         Propane.RecordKey K ,  System.Param_RecordKey R
 ON 
              K.IndexId = R.IndexId
              And K.RecordNumber = R.RecordNumber                       
              AND K.LookupKey <> R.LookupKey
WHERE     (R.ParameterKeyId = @key)


UPDATE    Propane.RecordKey
With (TabLock)
SET              LookupKey = System.Param_RecordKey.LookupKey
FROM         Propane.RecordKey K ,  System.Param_RecordKey R
 ON 
              K.IndexId = R.IndexId
              And K.RecordNumber = R.RecordNumber                       
               WHERE     (R.ParameterKeyId = @key) and K.LookupKey not in          (Select LookupKey from System.Param_RecordKey)
于 2016-01-19T21:53:00.877 に答える