web-dev-qa-db-ja.com

TRUNCATEとDELETE FROMの長所と短所

誰かが私に次の2つのステートメントを使用することの長所と短所の簡単な概要を教えてもらえますか?

TRUNCATE TABLE dbo.MyTable

DELETE FROM dbo.MyTable

すべてが言われ、行われたとき、彼らは両方とも同じことをするようです。しかし、2つの間に違いがなければなりません。

59
Jim B

TRUNCATEはロールバックデータを生成しないため、高速になります。テーブルで使用されるデータページの割り当てを解除するだけです。

ただし、トランザクション中にこの削除を「元に戻す」機能が必要な場合は、DELETE FROM、ロールバックする機能を提供します。

EDIT:上記はSQL Serverには正しくないことに注意してください(ただし、Oracleには適用されます)。 SQL Serverでは、トランザクション内にいて、トランザクションがコミットされていない場合、切り捨て操作をロールバックできます。 SQL Serverの観点から見ると、DELETE FROMとTRUNCATEの重要な違いの1つは this : "DELETEステートメントは、一度に1行ずつ削除し、削除された各行のトランザクションログにエントリを記録します。テーブルデータの格納に使用されるデータページの割り当てを解除してデータを割り当て、トランザクションログにページの割り当て解除のみを記録します。

つまり、ページの割り当て解除のみがトランザクションログに記録されるため、TRUNCATE中のロギングは少なくなりますが、DELETE FROMでは各行の削除が記録されます。それがTRUNCATEが非常に速い理由の1つです。

また、そのMSDNリンクから、外部キー制約によって参照されているテーブル、インデックス付きビューに参加しているテーブル、またはトランザクションレプリケーションまたはマージレプリケーションを使用して公開されているテーブルを切り捨てることができないことに注意してください。

EDIT 2:もう1つの重要な点は、TRUNCATE TABLEがIDを初期シードにリセットするのに対し、DELETE FROMは中断したところから増分を続けることです。参照:ベンロビンソンの答え。

83
dcp

他の回答で言及されていないもう1つの重要な点は、TRUNCATE TABLE will reset your 初期シードと同一、一方DELETE FROMは、中断したところからインクリメントを続けます。

46
Ben Robinson

セキュリティの観点からのもう1つの違いは、TRUNCATEにはテーブルに対するALTER権限が必要ですが、DELETEにはそのテーブルに対する(ドラムロール)DELETEパーミッションが必要なだけであるということです。

8
Kyle Hale

TRUNCATE TABLEはトランザクションを記録しません。これは、大きなテーブルの場合に非常に高速であることを意味します。欠点は、操作を取り消せないことです。

DELETE FROMは削除されている各行をトランザクションログに記録するため、操作に時間がかかり、トランザクションログが劇的に大きくなります。利点は、必要に応じて操作を元に戻すことができることです。

4
Justin Niessner

SQLサーバーでの削除と切り捨ての概要

完全な記事については、この接続の後に行ってください: SQL Serverで削除と切り捨て

enter image description here

/*Truncate - Syntax*/
TRUNCATE TABLE table_name

/*Delete - Syntax*/
DELETE FROM table_name
WHERE some_condition
3
Rahul Modi

削除と切り捨ては、操作が明示的なトランザクションで実行された場合にのみロールバックできると考えています。それ以外の場合は、削除されたデータを復元するために復元を実行する必要があります

2
CNkatcher

基本的な違いは、ログの記録方法です。 DELETEとTRUNCATEは異なる方法で記録されますが、どちらもまったく同じ方法でロールバックできます。データを変更するすべての操作が記録されます。 SQL Serverには、ログに記録されない操作などはありません。

1
nvogel

さらに、Truncateはテーブルのdelete triggerをトリガーしませんが、deleteステートメントはそれぞれのテーブルのdelete triggerをトリガーすることを考慮する別のポイント行。

0
Melad Basilius

非常に重要(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時間もスタックします。ただし、そのTRUNCATEDELETE FROMに置き換えると、テーブルにSch-Sロックがなくなり、上記のクエリが停止しないことがわかります。

0
sotn

DELETETRUNCATEのもう1つの違いは、テーブルが破損したときの動作です。

例えば:

DELETE FROM table_name;

エラーになります:

メッセージ3314、レベル21、状態3、行1

データベース '...'でログに記録された操作を元に戻すときに、ログレコードID()でエラーが発生しました。通常、特定の障害は以前にWindowsイベントログサービスのエラーとして記録されます。バックアップからデータベースまたはファイルを復元するか、データベースを修復します。

メッセージ0、レベル20、状態0、行0

現在のコマンドで重大なエラーが発生しました。結果があれば、破棄する必要があります。

TRUNCATEは機能しますが:

TRUNCATE TABLE table_name;
-- Command(s) completed successfully.
0
Lukasz Szozda