TRUNCATE PARTITION in SQL Server
TRUNCATE TABLE
removes all rows from a table, but the table structure and its columns, constraints, indexes, and so on remain. That is what the documentation says and that is what we daily use in our scripts, jobs and SSIS packages. Starting with SQL Server 2016 such operation can be done also on a partition level giving extra flexibility and convenience.
Directly to an example:
Partition truncation in SQL Server 2016 as simple as following line of code:
--SQL Server Execution Times: CPU time = 0 ms, elapsed time = 324 ms. TRUNCATE TABLE dbo.PartitionedTable WITH (PARTITIONS (1, 6 TO 10));
The command has removed partitions: 1, 6, 7, 8, 9, 10. Each one held one million rows, therefore, 6 000 000 rows removed in a 324 ms. This is amazing result which outperform PARTITION SWITCHING
timings.
Behind of the hood, TRUNCATE
is a DDL command and this fact is a reason of superior performance of rows/pages release. However, it also leads to requirement of the minimum permission level on an object – ALTER TABLE
.
Another necessary part of the command is the list of partition ids to remove corresponding segment. Partition Id can be obtained multiple ways. As example, via $PARTITION.partition
function call. Following query has been executed before and after truncation:
SELECT $PARTITION.[PartitioningByRowID] (RowId) AS PartitionID , COUNT(*) AS [RowCount] , MIN(RowId) AS MinRowID , MAX(RowId) AS MaxRowID FROM dbo.PartitionedTable GROUP BY $PARTITION.[PartitioningByRowID] (RowId)
Alternative way to get partition ids and metadata is by querying querying dynamic management object – sys.dm_db_partition_stats.
Test the feature in own sandbox?
Following script has necessary parts to reproduce this operation on your side:
-- step 1: build partition function and partition scheme CREATE PARTITION FUNCTION [PartitioningByRowID] (int) AS RANGE RIGHT FOR VALUES (1000000, 2000000, 3000000,4000000, 5000000 , 6000000, 7000000, 8000000, 9000000,10000000); CREATE PARTITION SCHEME [PartitionByRowID] AS PARTITION [PartitioningByRowID] TO ([PRIMARY], [PRIMARY], [PRIMARY], [PRIMARY], [PRIMARY] , [PRIMARY], [PRIMARY], [PRIMARY], [PRIMARY], [PRIMARY], [PRIMARY]); -- step 2: create partitioned table CREATE TABLE [dbo].[PartitionedTable]( [RowId] [INT] NOT NULL, [DataFiller] [char](500) NULL, [DateInserted] [datetime] NOT NULL ) ON [PartitionByRowID](RowID) GO -- step 3: build a table INSERT dbo.PartitionedTable SELECT TOP 10000000 s3.number * 1000000 + s2.number * 1000 + s1.number AS RowId , CAST(replicate ('a',500) AS CHAR(500)) AS DataFiller , GETDATE() AS DateInserted FROM master..spt_values s1 CROSS JOIN master..spt_values s2 CROSS JOIN master..spt_values s3 WHERE s1.number BETWEEN 0 AND 999 AND s1.type = 'P' AND s2.number BETWEEN 0 AND 999 AND s2.type = 'P' AND s3.number BETWEEN 0 AND 9 AND s3.type = 'P' ORDER BY 1 -- step 4: get number of rows per partition SELECT $PARTITION.[PartitioningByRowID] (RowId) AS PartitionID , COUNT(*) AS [RowCount] , MIN(RowId) AS MinRowID , MAX(RowId) AS MaxRowID FROM dbo.PartitionedTable GROUP BY $PARTITION.[PartitioningByRowID] (RowId) SET STATISTICS IO, TIME ON -- step 5: perform partition truncation --SQL Server Execution Times: CPU time = 0 ms, elapsed time = 324 ms. TRUNCATE TABLE dbo.PartitionedTable WITH (PARTITIONS (1, 6 TO 10));