web-dev-qa-db-ja.com

大きなINフィルターと使用のトランザクションレベルの違い。 「BEGINTRAN / COMMIT」

サーバーのオーバーヘッドを最小限に抑えて、約100,000件のレコードを削除したいと思います。適切にテストできなかったいくつかのやっかいな質問があったので、ここで何人かの専門家に尋ねると思いました。どちらが良いでしょう:

1-

BEGIN TRAN
DELETE FROM dbo.x
WHERE ID IN (
1
,2
,3
,4
...
,100000
)
COMMIT

2-

BEGIN TRAN
DELETE FROM dbo.x
WHERE ID = 1
GO
DELETE FROM dbo.x
WHERE ID = 2
GO
...
COMMIT 

3-3-

DELETE FROM dbo.x
WHERE ID = 1
GO
DELETE FROM dbo.x
WHERE ID = 2
GO
...

私の想定では、#1はサンプル%に基づいてスキャンを実行し、アイテムを選択して削除し、一連のトランザクションとしてログに記録します。おそらく、各indvlではなく、変更されたページに関する情報をトランザクションログに基づかせます。トランザクション。したがって、アクティビティ全体をロールバックしてページにコメントを付けることしかできません。または、コミットすることもできます。あれは正しいですか?

#2では、SQL Serverストレージエンジンがこれらすべてを1つの大きなトランザクションにロールバックできないようにすることで、GOステートメントによってトランザクションログアクティビティが大幅に増えると思いますが、それでもBEGINTRANを使用してトランザクションログを最適化します。 -COMMITブロック。したがって、#3よりも効果的ですが、#1よりも効果的ではありません。

次に、各indvlとして#3が最悪のものになると思います。トランザクションがログに記録されます。

誰かが良いブログ投稿やテストシナリオを持っているなら、彼らは私にそれも素晴らしいだろうと指摘することができます。トランザクションログを深く掘り下げて自分で理解する方法を検討しましたが、この時点で、皆さんに聞いてみようと思いました。

ありがとう!

2
Ali Razeghi

ロギングの観点から、1と2は、単一のトランザクション内ですべての削除を実行している場合とほぼ同じになります。削除の実行中は、多くのロックとおそらくブロックが発生します。 #3はバッチごとに1つのトランザクションであるため、ユーザーへの影響はそれほど大きくなく、トランザクションログには大きなトランザクションではなく小さなトランザクションが多数含まれます。 #2と#3の実行には、ほぼ同じ時間がかかります。 #1は1つのコマンドであるため、#2および#3よりも時間がかからないはずですが、実行時に問題が発生する可能性があります。

私はおそらくこのようなことをしたいと思います。これにより、一度に1000行のみを処理することで、発生する必要のあるロックとブロックが最小限に抑えられます。

SELECT NULL
WHILE @@ROWCOUNT <> 0
BEGIN
  DELETE TOP (1000) FROM dbo.x
  WHERE ID IN ( /* if possible use "BETWEEN 1 and 100000" instead*/
  1
  ,2
  ,3
  ,4
  ...
  ,100000
  )
END
3
mrdenny