回答:
SQL Serverの場合、コミット操作はLOP_COMMIT_XACTをログファイルに書き込んでロックを解除するだけであり、BEGIN TRAN以降にトランザクションが実行したすべてのアクションのROLLBACKよりも高速になることを主張できます。
コミットだけでなく、トランザクションのすべてのアクションを検討している場合、あなたのステートメントは真実ではないと主張します。外部要因、たとえばデータディスクの速度と比較したログディスクの速度を除くと、トランザクションによって行われた作業のロールバックは、そもそも作業を行うよりも速くなる可能性があります。
ロールバックとは、変更の順次ファイルを読み取り、それらをメモリ内のデータページに適用することです。元の「作業」では、実行計画の生成、ページの取得、行の結合などが必要でした。
編集:それはビットに依存します...
@JackDouglasは、ロールバックが元の操作よりも大幅に長くなる可能性がある状況の1つを説明するこの記事を指摘しました。この例は、必然的に並列処理を使用する14時間のトランザクションで、ロールバックはほとんどシングルスレッドであるため、ロールバックに48時間以上かかります。また、バッファプールを繰り返しかき回している可能性が高いため、メモリ内ページへの変更を元に戻すことはできません。
だから、私の以前の答えの改訂版。ロールバックはどれくらい遅くなりますか?他のすべてが考慮されますが、典型的なOLTPトランザクションではそうではありません。典型的な範囲外では、「行う」よりも「元に戻す」のに時間がかかることがありますが、(これは潜在的な言い回しですか?)なぜ「行う」が行われたかに依存します。
Edit2:コメントでの議論に続いて、ここで行われている作業が操作としてのコミットとロールバックの相対的な費用を決定する主要な要因であることを示す非常に不自然な例です。
2つのテーブルを作成し、非効率的にパックします(ページごとの無駄なスペース):
SET STATISTICS IO OFF;
SET STATISTICS TIME OFF;
SET NOCOUNT ON;
GO
CREATE TABLE dbo.Foo
(
col1 INT IDENTITY(1,1) PRIMARY KEY CLUSTERED
, col2 CHAR(4000) NOT NULL DEFAULT REPLICATE('A', 4000)
)
CREATE TABLE dbo.Bar
(
col1 INT IDENTITY(1,1) PRIMARY KEY CLUSTERED
, col2 CHAR(4000) NOT NULL DEFAULT REPLICATE('A', 4000)
)
GO
INSERT dbo.Foo DEFAULT VALUES
GO 100000
INSERT dbo.Bar DEFAULT VALUES
GO 100000
「悪い」更新クエリを実行し、作業にかかる時間とコミットの発行にかかる時間を測定します。
DECLARE
@StartTime DATETIME2
, @Rows INT
SET @Rows = 1
CHECKPOINT
DBCC DROPCLEANBUFFERS
BEGIN TRANSACTION
SET @StartTime = SYSDATETIME()
UPDATE
dbo.bar
SET
col2 = REPLICATE('B', 4000)
FROM
dbo.bar b
INNER JOIN
(
SELECT TOP(@Rows)
col1
FROM
dbo.foo
ORDER BY
NEWID()
) f
ON f.col1 = b.col1
OPTION (MAXDOP 1)
SELECT 'Find and update row', DATEDIFF(ms, @StartTime, SYSDATETIME())
SET @StartTime = SYSDATETIME()
COMMIT TRANSACTION
SELECT 'Commit', DATEDIFF(ms, @StartTime, SYSDATETIME())
GO
同じことを再度行いますが、ロールバックを発行して測定します。
DECLARE
@StartTime DATETIME2
, @Rows INT
SET @Rows = 1
CHECKPOINT
DBCC DROPCLEANBUFFERS
BEGIN TRANSACTION
SET @StartTime = SYSDATETIME()
UPDATE
dbo.bar
SET
col2 = REPLICATE('B', 4000)
FROM
dbo.bar b
INNER JOIN
(
SELECT TOP(@Rows)
col1
FROM
dbo.foo
ORDER BY
NEWID()
) f
ON f.col1 = b.col1
OPTION (MAXDOP 1)
SELECT 'Find and update row', DATEDIFF(ms, @StartTime, SYSDATETIME())
SET @StartTime = SYSDATETIME()
ROLLBACK TRANSACTION
SELECT 'Rollback', DATEDIFF(ms, @StartTime, SYSDATETIME())
GO
@ Rows = 1の場合、かなり一貫した結果が得られます。
@ Rows = 100の場合:
@ Rows = 1000の場合:
元の質問に戻ります。作業に加えてコミットにかかる時間を測定する場合、その作業の大部分は実際にデータを変更するのではなく、更新する行を見つけることに費やされるため、ロールバックが勝ちです。コミット操作を単独で見ている場合、コミットがそのような「作業」をほとんど行わないことは明らかです。コミットは「完了」です。
begin tran
トランザクションのカウンターが増えることは知っていました。私があなたを理解していれば、rdbmsはCOMMITですべてのタスクを実行しています(行を結合し、実行計画を生成します...)?
Oracleの場合、ロールバックは、ロールバックする変更を行うのにかかった時間よりも何倍も長くかかる場合があります。多くの場合、これは重要ではありません。
SQL Serverの場合、状況が同じかどうかはわかりませんが、そうでない場合は誰かが言うでしょう...
「なぜ」については、私が言うと思いますrollback
する必要があります珍しい何かがなくなって間違っていて、もちろん通常場合にのみ、commit
はるかに一般的である可能性が高い-それはのために最適化するには理にかなっているように、commit
ロールバックは、「ああ、気にしない」だけではありません-多くの場合、それはすでに行ったことを取り消す必要があります。元のトランザクションが並行して実行された場合でも、ロールバックはシングルスレッドですが、ロールバック操作が常に元の操作よりも遅い、または常に速いというルールはありません。あなたが待っているなら、ただ待っておくのが最も安全だと思います。
もちろん、これはすべてSQL Server 2019でのすべての変更と、加速データベース回復(これも可変であるペナルティがありますが、データのサイズに関係なく瞬時にロールバックできます)。
すべてのトランザクションのコミットアクティビティのパフォーマンスがロールバックよりも優れているわけではありません。そのようなケースの1つは、SQLの削除操作です。トランザクションが行を削除すると、これらの行はゴーストレコードとしてマークされます。コミットが発行され、ゴーストレコードのクリーンアップタスクが開始されると、これらのレコードのみが「削除」されます。
代わりにロールバックが発行された場合、これらのレコードからゴーストマーキングが削除されるだけで、集中的な挿入ステートメントは削除されません。
すべてではありません。PostgreSQLは、ディスクI / Oの点で2つの操作が事実上同一であるため、コミットするよりもロールバックするのに時間がかかりません。私は実際に、これがコミットのために最適化されることの問題であるとは思いません。
基本的な質問は、ディスク上のレイアウトにどのように対処し、これがコミットとロールバックにどのように影響するかです。コミットよりもゆっくりとロールバックする主要なデータベースは、特にクラスター化されたテーブルからメインのデータ構造からデータを移動し、データの更新時にロールバックセグメントに入れる傾向があります。つまり、コミットするにはロールバックセグメントをドロップするだけですが、ロールバックするにはすべてのデータをコピーする必要があります。
PostgreSQLの場合、すべてのテーブルはヒープテーブルであり、インデックスは別個です。これは、ロールバックまたはコミットするときに、データを再配置する必要がないことを意味します。これにより、コミットとロールバックの両方が高速になります。
ただし、他のいくつかの処理が少し遅くなります。たとえば、プライマリキールックアップは、インデックスファイルをトラバースし、次にヒープテーブルにヒットする必要があります(適用可能なインデックスがカバーされていない場合)。これは大したことではありませんが、他の情報と可視性をチェックするために、余分なページ検索またはおそらくいくつかのランダムなページ検索(その行で多くの更新が発生した場合)を追加します。
ただし、ここでの速度は、PostgreSQLでの書き込み操作と読み取り操作の最適化の問題ではありません。一部の読み取り操作を他の読み取り操作よりも優先することは不本意です。その結果、PostgreSQLは他のデータベースと同様に平均して実行されます。より高速または低速になる可能性があるのは、特定の操作だけです。
だから、実際の答えは、データベースは読み取り側の特定のワークロード向けに最適化され、これが書き込み側の課題につながるということだと思います。通常、質問がある場合、コミットは常にではありませんが、通常はロールバックよりも優先されます。ただし、これはどちらかを行うことの意味に依存します(更新は削除とは異なります)。