Delete, Truncate, or Drop?

  • If you do not need the table anymore for sure, drop it.
  • If you do not need all of the data in the table, but you want to keep the table structure including constraints and indexes, use Truncate. The truncate command works at the page level, not at the row level as the Delete command
  • If you may need the data at a later time, use Delete. But be sure to have a clustered index on the table before the deletion. The clustered index will minimize the number of pages left in the system after the deletion. But keep in mind that, even some pages keep in the system after deletion, these pages can be re-used by SQL Server, you typically do not need to do anything to vacuum them.


--Demo: Difference between Delete and Truncate and how a clustered index can help the space relieved.


--Create a heap table

USE [AdventureWorks2008R2]

GO

 

CREATE TABLE [Sales].[SalesOrderDetail_hash]

    (

      [SalesOrderID] [int] NOT NULL ,

      [SalesOrderDetailID] [int] ,

      [CarrierTrackingNumber] [nvarchar](25) NULL ,

      [OrderQty] [smallint] NOT NULL ,

      [ProductID] [int] NOT NULL ,

      [SpecialOfferID] [int] NOT NULL ,

      [UnitPrice] [money] NOT NULL ,

      [UnitPriceDiscount] [money] NOT NULL ,

      [LineTotal] NUMERIC(38, 6) ,

      [rowguid] [uniqueidentifier] ,

      [ModifiedDate] [datetime]

    )

ON  [PRIMARY]

GO

 

--populate data to the heap table

INSERT  INTO [Sales].[SalesOrderDetail_hash]

        SELECT  *

        FROM    [Sales].[SalesOrderDetail]

 

-- create a clustered index table

CREATE TABLE [Sales].[SalesOrderDetail_C]

    (

      [SalesOrderID] [int] NOT NULL ,

      [SalesOrderDetailID] [int] ,

      [CarrierTrackingNumber] [nvarchar](25) NULL ,

      [OrderQty] [smallint] NOT NULL ,

      [ProductID] [int] NOT NULL ,

      [SpecialOfferID] [int] NOT NULL ,

      [UnitPrice] [money] NOT NULL ,

      [UnitPriceDiscount] [money] NOT NULL ,

      [LineTotal] NUMERIC(38, 6) ,

      [rowguid] [uniqueidentifier] ,

      [ModifiedDate] [datetime] ,

      CONSTRAINT [PK_SalesOrderDetailC_SalesOrderID_SalesOrderDetailID] PRIMARY KEY CLUSTERED

        ( [SalesOrderID] ASC, [SalesOrderDetailID] ASC ) ON [PRIMARY]

    )

ON  [PRIMARY]

GO

 

--populate data to the clustered index table

INSERT  INTO [Sales].[SalesOrderDetail_C]

        SELECT  *

        FROM    [Sales].[SalesOrderDetail]

go

 

-- create a non-clustered index table

CREATE TABLE [Sales].[SalesOrderDetail_N]

    (

      [SalesOrderID] [int] NOT NULL ,

      [SalesOrderDetailID] [int] ,

      [CarrierTrackingNumber] [nvarchar](25) NULL ,

      [OrderQty] [smallint] NOT NULL ,

      [ProductID] [int] NOT NULL ,

      [SpecialOfferID] [int] NOT NULL ,

      [UnitPrice] [money] NOT NULL ,

      [UnitPriceDiscount] [money] NOT NULL ,

      [LineTotal] NUMERIC(38, 6) ,

      [rowguid] [uniqueidentifier] ,

      [ModifiedDate] [datetime] ,

      CONSTRAINT [PK_SalesOrderDetailN_SalesOrderID_SalesOrderDetailID] PRIMARY KEY NONCLUSTERED

        ( [SalesOrderID] ASC, [SalesOrderDetailID] ASC ) ON [PRIMARY]

    )

ON  [PRIMARY]

GO

 

--populate data to the non-clustered index table

INSERT  INTO [Sales].[SalesOrderDetail_N]

        SELECT  *

        FROM    [Sales].[SalesOrderDetail]

Go

 

--Delete the three tables

DELETE  [Sales].[SalesOrderDetail_hash]

GO

DELETE  [Sales].[SalesOrderDetail_C]

GO

DELETE  [Sales].[SalesOrderDetail_N]

GO

 

--82 pages left after the deleting the heap table

SELECT  *

FROM    sys.Dm_db_index_physical_stats(DB_ID('Adventureworks2008R2'),

                                       OBJECT_ID('[Sales].[SalesOrderDetail_hash]'),

                                       NULL, NULL, NULL)

 

 

--79 (=66+13) pages left after the deleting the non-clustered index table

SELECT  *

FROM    sys.Dm_db_index_physical_stats(DB_ID('Adventureworks2008R2'),

                                       OBJECT_ID('[Sales].[SalesOrderDetail_N]'),

                                       NULL, NULL, NULL)

                                      

--Only 1 page left after the deleting the clustered index table

SELECT  *

FROM    sys.Dm_db_index_physical_stats(DB_ID('Adventureworks2008R2'),

                                       OBJECT_ID('[Sales].[SalesOrderDetail_C]'),

                                       NULL, NULL, NULL)

 

--How about truncating the tables?

TRUNCATE TABLE [Sales].[SalesOrderDetail_hash]

 

--No pages left at all if truncating the table

SELECT  *

FROM    sys.Dm_db_index_physical_stats(DB_ID('Adventureworks2008R2'),

                                       OBJECT_ID('[Sales].[SalesOrderDetail_hash]'),

                                       NULL, NULL, NULL)