次の2つのステートメントを使用することの長所と短所の概要を教えてもらえますか。
TRUNCATE TABLE dbo.MyTable
vs
DELETE FROM dbo.MyTable
すべてが言われ、行われるとき、彼らは両方とも同じことをするようです。しかし、2つの間に違いがあるはずです。
次の2つのステートメントを使用することの長所と短所の概要を教えてもらえますか。
TRUNCATE TABLE dbo.MyTable
vs
DELETE FROM dbo.MyTable
すべてが言われ、行われるとき、彼らは両方とも同じことをするようです。しかし、2つの間に違いがあるはずです。
TRUNCATE
ロールバックデータを生成しないため、非常に高速です。テーブルで使用されているデータページの割り当てを解除するだけです。
ただし、トランザクション中にこの削除を「元に戻す」機能が必要な場合はDELETE FROM
、を使用する必要があります。これにより、ロールバックが可能になります。
編集: 上記はSQL Serverには正しくないことに注意してください(ただし、Oracleには適用されます)。SQL Serverでは、トランザクション内にいて、トランザクションがコミットされていない場合、切り捨て操作をロールバックすることができます。SQL Serverの観点から見ると、DELETE FROMとTRUNCATEの主な違いは次のとおりです。「DELETEステートメントは一度に1行ずつ削除し、削除された各行のトランザクションログにエントリを記録します。TRUNCATETABLEは、データページの割り当てを解除してデータを削除します。テーブルデータを保存し、ページの割り当て解除のみをトランザクションログに記録するために使用されます。」
つまり、ページの割り当て解除のみがトランザクションログに記録されるため、TRUNCATE中のログは少なくなりますが、DELETE FROMを使用すると、各行の削除が記録されます。これが、TRUNCATEが非常に高速である理由の1つです。
また、MSDNリンクから、外部キー制約によって参照されているテーブル、インデックス付きビューに参加しているテーブル、またはトランザクションレプリケーションまたはマージレプリケーションを使用して公開されているテーブルを切り捨てることはできないことに注意してください。
編集2: もう1つの重要なポイントは、TRUNCATE TABLEがIDを最初のシードにリセットするのに対し、DELETEFROMは中断したところからインクリメントを続けることです。参照:ベンロビンソンの答え。
他の回答で言及されていないもう1つの重要なポイントは、 IDを最初のシードTRUNCATE TABLE
にリセットする一方で、中断したところから増分を続けることです。DELETE FROM
セキュリティの観点からのもう1つの違いは、TRUNCATEにはテーブルに対するALTER権限が必要であるのに対し、DELETEにはそのテーブルに対する(ドラムロール)DELETE権限が必要なだけであるということです。
TRUNCATE TABLE
トランザクションをログに記録しません。つまり、大きなテーブルでは非常に高速です。欠点は、操作を元に戻せないことです。
DELETE FROM
削除される各行をトランザクションログに記録するため、操作に時間がかかり、トランザクションログが大幅に増加します。利点は、必要に応じて操作を元に戻すことができることです。
SQLサーバーでの削除と切り捨ての概要
完全な記事については、この接続の後に取得してください:SQLServerでVsTruncateを削除します
/*Truncate - Syntax*/
TRUNCATE TABLE table_name
/*Delete - Syntax*/
DELETE FROM table_name
WHERE some_condition
DeleteとTruncateは、操作が明示的なトランザクションで実行された場合にのみロールバックできると思います。それ以外の場合は、削除されたデータを回復するために復元を実行する必要があります
基本的な違いは、ログに記録される方法にあります。DELETEとTRUNCATEのログは異なりますが、どちらもまったく同じ方法でロールバックできます。データを変更するすべての操作がログに記録されます。SQL Serverには、ログに記録されない操作などはありません。
非常に重要で(imo)、他の回答で言及されていないことの1つは、行ロックを使用するのに対しTRUNCATE
、スキーマ安定性ロックが必要なことです。以下を調べてみましょう。Sch-S
DELETE
BEGIN TRANSACTION;
BEGIN TRY
-- Truncate below will take LCK_M_SCH_S lock for TABLE_A
TRUNCATE TABLE TABLE_A
-- Lets say the query below takes 5 hours to execute
INSERT INTO
TABLE_A
SELECT
*
FROM
GIANT_TABLE (NOLOCK)
END TRY
BEGIN CATCH
IF @@TRANCOUNT > 0
ROLLBACK TRANSACTION;
THROW
END CATCH
IF @@TRANCOUNT > 0
COMMIT TRANSACTION;
ここで、このクエリの開始から1〜2分後に、次のコマンドを実行しようとしたとします。
SELECT COUNT(*) FROM TABLE_A (NOLOCK)
NOLOCK
句を使用したことに注意してください。今何が起こると思いますか?このクエリは5時間待機します。なんで?句はロックオンNOLOCK
する必要がありますが、その句はすでにロックオンしているためです。まだトランザクションをコミットしていないため、その句の後でもロックはオンのままです。テーブルのロックとは、基本的に、列の追加/削除などによって変更されているか、切り捨てられていることを意味します。以下のようなものを実行することさえできません:Sch-S
TABLE_A
TRUNCATE
Sch-S
TRUNCATE
Sch-S
TABLE_A
SELECT object_id('TABLE_A')
これも5時間スタックします。ただし、これをに置き換えるとTRUNCATE
、テーブルにロックDELETE FROM
がなくSch-S
、上記のクエリがスタックしないことがわかります。
DELETE
vsのもう1つの違いTRUNCATE
は、テーブルが破損した場合の動作です。
例えば:
DELETE FROM table_name;
エラーが発生します:
メッセージ3314、レベル21、状態3、行1
データベース'...'でログに記録された操作を元に戻すときに、ログレコードID()でエラーが発生しました。通常、特定の障害は、Windowsイベントログサービスのエラーとして以前にログに記録されます。バックアップからデータベースまたはファイルを復元するか、データベースを修復します。
メッセージ0、レベル20、状態0、行0
現在のコマンドで重大なエラーが発生しました。結果がある場合は、破棄する必要があります。
動作しTRUNCATE
ますが:
TRUNCATE TABLE table_name;
-- Command(s) completed successfully.
さらに、すべての回答に加えて、考慮すべきもう1つのポイントは、テーブルのをTruncate
トリガーしませんが、ステートメントは各行のテーブルのをトリガーします。delete trigger
delete
delete trigger
truncateはログを記録しませんが、deleteはログを実行します。そのため、大量のレコードがある場合、トランスログは膨大になります。