sql >> データベース >  >> RDS >> Database

パフォーマンスの神話:切り捨てられたカントはロールバックされます

    ゲスト作成者:Derik Hammer(@SQLHammer)


    TRUNCATETABLEとDELETEの違いは誤解されることがよくあります。 TRUNCATETABLEはロールバックできないという神話を反証しようとしています:

    「TRUNCATETABLEはログに記録されないため、ロールバックできません。トランザクションの場合は、DELETEを使用する必要があります。」

    マニュアルを読む

    TRUNCATETABLEに関するBooksOnlineの記事はかなり説明的です:

    「個々の行の削除をログに記録せずに、テーブルまたはテーブルの指定されたパーティションからすべての行を削除します。 TRUNCATE TABLEは、WHERE句のないDELETEステートメントに似ています。ただし、TRUNCATE TABLEはより高速で、使用するシステムおよびトランザクションログリソースが少なくなります。」

    TRUNCATETABLEが使用する少ないという事実 トランザクションログリソースは、ある程度トランザクションログに書き込むことを意味します。どれだけの量を調べて、ロールバックできるかを調べてみましょう。

    証明する

    以前の投稿で、ポールランダルはこれを細心の注意を払って説明しましたが、この神話の両方の要素を反証するために非常に単純な再現を提供することが有用だと思いました。

    TRUNCATE TABLEをロールバックできますか?

    TRUNCATETABLEをロールバックできることを証明するのは簡単です。 TRUNCATE TABLEをトランザクションに入れて、ロールバックします。

    USE demo;
    BEGIN TRANSACTION;
      SELECT COUNT(*) [StartingTableRowCount] FROM [dbo].[Test];
      TRUNCATE TABLE [dbo].[Test];
      SELECT COUNT(*) [TableRowCountAfterTruncate] FROM [dbo].[Test];
    ROLLBACK TRANSACTION;
    SELECT COUNT(*) [TableRowCountAfterRollback] FROM [dbo].[Test];

    テーブルには100,000行あり、ロールバック後に100,000行に戻ります:

    TRUNCATE TABLEはログに書き込みますか?

    チェックポイントを実行することにより、クリーンな開始点を取得します。次に、TRUNCATETABLEの前後のログレコードを確認できます。

    USE demo;
    CHECKPOINT;
     
      SELECT COUNT(*) [StartingLogRowCount]
      FROM sys.fn_dblog (NULL, NULL);
     
      TRUNCATE TABLE [dbo].[Test];
     
      SELECT COUNT(*) [LogRowCountAfterTruncate]
      FROM sys.fn_dblog (NULL, NULL);

    TRUNCATE TABLEコマンドは、237個のログレコードを生成しました(少なくとも最初は)。これにより、ロールバックを実行できるようになり、SQLServerが最初に変更を登録する方法がわかります。

    DELETEについてはどうですか?

    DELETEとTRUNCATETABLEの両方がログに書き込み、ロールバックできる場合、それらの違いは何ですか?

    上記のBOLリファレンスで述べたように、TRUNCATETABLEはより少ないシステムおよびトランザクションログリソースを使用します。 TRUNCATETABLEコマンドに対して237個のログレコードが書き込まれたことはすでに確認しました。それでは、DELETEを見てみましょう。

    USE demo;
    CHECKPOINT;
     
      SELECT COUNT(*) [StartingLogRowCount]
      FROM sys.fn_dblog (NULL, NULL);
     
      DELETE FROM [dbo].[Test];
     
      SELECT COUNT(*) [LogRowCountAfterDelete]
      FROM sys.fn_dblog (NULL, NULL);

    DELETE用に440,000を超えるログレコードが書き込まれるため、TRUNCATEコマンドの方が明らかにはるかに効率的です。

    まとめ

    TRUNCATE TABLEはログに記録されたコマンドであり、ロールバックでき、同等のDELETEよりもパフォーマンスが大幅に向上します。テーブルに存在するよりも少ない行を削除する場合は、DELETEが重要になります(TRUNCATE TABLEはWHERE句を受け入れないため)。 DELETEをより効率的にするためのアイデアについては、AaronBertrandの投稿「大規模な削除操作をチャンクに分割する」を参照してください。

    作者について

    Derikは、SQLServerに焦点を当てたデータプロフェッショナルであり、新しく作成されたMicrosoft DataPlatformMVPです。彼の情熱は、高可用性、災害復旧、継続的インテグレーション、自動メンテナンスに重点を置いています。彼の経験は、金融およびヘルスケア業界で働く長期的なデータベース管理、コンサルティング、および起業家のベンチャーに及びました。彼は現在、Subway FranchiseWorldHeadquartersのデータベース運用チームを担当する上級データベース管理者です。デリックは、時間外、またはSQLHammer.comでブログを書いているとき以外は、コネチカット州スタンフォードにあるFairfieldPASSSQLServerユーザーグループのチャプターリーダーとして#sqlfamilyに時間を費やしています。
    1. CONVERT()を使用してSQLServerで1つの日付形式から別の日付形式に変換する方法

    2. CloverDXでODBCデータを変換する

    3. Oracle SELECTTOP10レコード

    4. SQLServerSMOがDLLの欠落について不平を言う