/ notes / sql

Sql Server : Indexes rebuild tests

Here some tests I have done to better understand the behavior of indexes rebuild in SQL Server.

I used the database ContosoDataGeneratorV2 size “10M”. I added the extra table [Customer2] : it is a clone (structure+data) of [Customer]. It is not referenced by other tables and has 4 indexes on GeoAreaKey, GivenName, StartDT and EndDT.

Here’s the indexes involved in the tests (script at the end of the page for creating the report):

SchemaName  TableName  IndexName                IndexType     IndexSizeMB
-------------------------------------------------------------------------
Data        Customer   PK_Customer              CLUSTERED          610.90
Data        Sales      IX_Sales_CustomerKey     NONCLUSTERED       450.85
Data        Sales      IX_Sales_ProductKey      NONCLUSTERED       450.85
Data        Sales      IX_Sales_StoreKey        NONCLUSTERED       450.85
Data        Sales      PK_Sales                 CLUSTERED         1764.11
Data        Customer2  IX_Customer2_EndDT       NONCLUSTERED        27.67
Data        Customer2  IX_Customer2_GeoAreaKey  NONCLUSTERED        22.78
Data        Customer2  IX_Customer2_GivenName   NONCLUSTERED        48.52
Data        Customer2  IX_Customer2_StartDT     NONCLUSTERED        27.67
Data        Customer2  PK_Customer2             CLUSTERED          612.78

I executed the testing queries Q1…Q12 measuring the space used on the MDF and LDF during the executions. To do that, I wrote a piece of C# to measure the MDF and LDF file usage. The database has been set to SIMPLE mode. The results are below.

ID Index (*) Action IndexSizeMB UsedMDF_MB UsedLDF_MB FinalDeltaMDF
Q1 IX_Sales_CustomerKey REBUILD 450 446 476 0
Q2 IX_Sales_StoreKey REBUILD 450 423 455 0
Q3 PK_Sales REBUILD 1764 1764 1886 0
Q4 PK_Sales DROP 1764 1120 1200 -249
Q5 PK_Sales ADD 1764 3100 3400 +249
Q6 (FK_Sales_Customers) DROP - 0 0 0
Q7 PK_Customer DROP 610 0 0 0
Q8 PK_Customer ADD 610 610 660 0
Q9 (FK_Sales_Customers) ADD - 0 0 0
Q10 PK_Customer REBUILD 610 593 637 0
Q11 PK_Customer2 DROP 610 132 120 0
Q12 PK_Customer2 ADD 610 738 789 0

Key findings:


Some charts

Below some charts that highlight the variation of MDF and LDF files during the execution of the commands.

Q2

Q2

Q5

Q5

Q12

Q12


Scripts

Testing commands

CHECKPOINT
GO

-- Q1
--ALTER INDEX [IX_Sales_CustomerKey] ON [Data].[Sales] REBUILD PARTITION = ALL WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)

-- Q2
--ALTER INDEX [IX_Sales_StoreKey] ON [Data].[Sales] REBUILD PARTITION = ALL WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)

-- Q3
--ALTER INDEX [PK_Sales] ON [Data].Sales REBUILD PARTITION = ALL WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)

-- Q4
--ALTER TABLE [Data].[Sales] DROP CONSTRAINT [PK_Sales] WITH ( ONLINE = OFF )
 
-- Q5
-- ALTER TABLE [Data].[Sales] ADD CONSTRAINT [PK_Sales] PRIMARY KEY CLUSTERED ([OrderKey] ASC,[LineNumber] ASC ) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]

-- Q6
-- ALTER TABLE [Data].[Sales] DROP CONSTRAINT [FK_Sales_Customers]

-- Q7
-- ALTER TABLE [Data].[Customer] DROP CONSTRAINT [PK_Customer] WITH ( ONLINE = OFF )

-- Q8
-- ALTER TABLE [Data].[Customer] ADD  CONSTRAINT [PK_Customer] PRIMARY KEY CLUSTERED  ([CustomerKey] ASC ) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]

-- Q9
-- ALTER TABLE [Data].[Sales] WITH NOCHECK ADD  CONSTRAINT [FK_Sales_Customers] FOREIGN KEY([CustomerKey]) REFERENCES [Data].[Customer] ([CustomerKey])
-- ALTER TABLE [Data].[Sales] CHECK CONSTRAINT [FK_Sales_Customers]

-- Q10
-- ALTER INDEX [PK_Customer] ON [Data].[Customer] REBUILD PARTITION = ALL WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)

-- Q11
-- ALTER TABLE [Data].[Customer2] DROP CONSTRAINT [PK_Customer2] WITH ( ONLINE = OFF )

-- Q12  
-- ALTER TABLE [Data].[Customer2] ADD CONSTRAINT [PK_Customer2] PRIMARY KEY CLUSTERED (CustomerKey,GeoAreaKey)  WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]

GO

CHECKPOINT
GO

Show index size

SELECT   
    sc.name AS SchemaName,
    t.name AS TableName,
    i.name AS IndexName,
    i.type_desc AS IndexType,
    SUM(s.used_page_count) * 8 / 1024.0 AS IndexSizeMB
FROM sys.dm_db_partition_stats  AS s
    JOIN sys.indexes  AS i ON s.[object_id] = i.[object_id] AND s.index_id = i.index_id
    JOIN sys.tables AS t ON s.object_id=t.object_id
    JOIN sys.schemas AS sc ON sc.schema_id = t.schema_id
GROUP BY 
    sc.name,t.name,i.name,i.type_desc
ORDER BY 
    sc.name,t.name,i.name,i.type_desc