web-dev-qa-db-ja.com

DELETEでTABLOCKXを回避できますか?

目標

ダウンタイムがゼロの3つのテーブルから古いレコード(約600GB)を数十億レコード削除します。

方法論と背景

100万のMyIDに関連付けられたレコードのバッチを一度に削除する予定です(つまり、MyID BETWEEN 1 AND 1000000)。削除の実行中、2つのテーブルは非常に高温になりますが、3番目のテーブルのアクティビティは安全に中断できます。 2つのホットテーブルでは、MyIDがクラスタリングキーです。 3番目のコールドテーブルでは、MyIDに非クラスター化インデックスがあります。

DELETE操作の他に、ホットテーブルの他のアクティビティは、おそらく1秒あたり数回のINSERTで構成されます。 MyIDはIDENTITYであり、新しく挿入されたレコードはどのDELETEバッチの範囲にも含まれません。

潜在的なパフォーマンスの理解に役立つ場合、これらの行のサンプルバッチの集約のSELECTは、MyIDによってクラスター化されたテーブルでは1秒未満、非クラスター化テーブルでは約2秒かかります。この特定のデータベースを再生するための製品レプリカがないので、削除にかかる時間はわかりませんが、これをDEVにデプロイすると、より良いアイデアが得られます。

補足:ログサイズに対処するために、これらのバッチをトランザクションにラップし、TLogバックアップの頻度を15分から5分に増やしています。 150GBの利用可能なログ領域があります。

質問

私はMSドキュメントを読みました:

デフォルトでは、DELETEステートメントは常に、変更するテーブルの排他(X)ロックを取得し、トランザクションが完了するまでそのロックを保持します。

ロックヒントの使用には非常に注意していますが、この場合、TABLOCKXを回避するために安全にヒントを使用できますか?ロックヒント以外に、TABLOCKXを回避する方法はありますか?

2
Cyndi Baker

数十億レコードの古いレコードを削除(約600GB)

この場合、削除するよりも残すべき行をコピーする方が便利な場合があります。すべての600Gbが確実にログファイルに移動することに注意してください。

デフォルトでは、DELETEステートメントは常に、変更するテーブルの排他(X)ロックを取得し、トランザクションが完了するまでそのロックを保持します。

これは間違っています。 SQL Serverは、対応するヒントが指定されていない限り、table lockで始まることはありません。

デフォルトでは、SQL Serverは最大の同時実行性を実現するために、可能な限り細かいロックを取得します。ほとんどの場合、これはSQL Serverが行(RIDまたはKEY)ロックを取得することを意味します。 SQL Serverは、問題を引き起こすことなく、単一のテーブル内のデータに対して数百または数千の個別のロックを取得できます。ただし、SQL Serverがクエリがクラスター化インデックス内の行の範囲にアクセスすると判断した場合は、代わりにページロックを取得することがあります。結局のところ、ページ上のすべての行にアクセスする場合、数十または数百の行ロックよりも単一のページロックを管理する方が簡単です。その他の場合、主にクエリの処理に役立つ使用可能なインデックスがない場合、SQL Serverはクエリの処理の開始時にテーブル全体をロックすることがあります。

PK範囲でフィルタリングする場合:MyID BETWEEN 1 AND 1000000それはおそらくpageロックで始まるでしょう。そして、ここでのすべては、1つのpageに収まるレコードの数に依存します。 pageの粒度で1000000レコードのロックにかかる時間が5000ロックよりも少ない場合、pageロックを使用すると問題ありません。ステートメントごとにlocksが増えると、lock escalationが発生し、テーブルは完全にロックされます。

...

インスタンス全体のしきい値を超えた場合のロックのエスカレーションに加えて、SQL Serverは、個々のセッションが1つのステートメントで5,000を超えるロックを取得した場合にもロックをエスカレートします。この場合、ロックをエスカレートするセッションを選択する際にランダム性はありません。ロックを取得したセッションです。

SQL Serverの同時実行性:K.Delaneyによるロック、ブロック、行のバージョン管理

したがって、取得したロックをテストおよび監視することによってのみ、最適なbatch sizeを見つけ、lock escalationを回避できます。テーブルのページあたりの行の平均がわかっている場合は、おおよそbatch sizeを計算できます。または、PAGLOCKを使用してページロックを強制し、テーブルのロックエスカレーションを無効にすることもできます。

ALTER TABLE MyTable SET ( LOCK_ESCALATION = DISABLE )
3
sepupic