In yesterday’s post A couple of things to be aware of when working with tables in SQL Azure I showed you some things to be aware of in regards to tables. Today let’s talk about how to rebuild an index

Let’s say you have a table with a clustered index on a uniqueidentifier column, you know that you have to use newid() instead of newsequentialid() since newsequentialid() is not supported. Clustering with newid() is not recommended because you will get page splits. Let’s take a look at how we can recreate the index

First create the following table with a clustered index

CREATE TABLE Test(bla uniqueidentifier default newid())

CREATE CLUSTERED INDEX ix_Test_bla on Test(bla)
GO

Now run the following block of code

;WITH CTE AS (SELECT 1 AS A 
			UNION ALL SELECT 2 
			UNION ALL SELECT 3 
			UNION ALL SELECT 4 
			UNION ALL SELECT 5
			UNION ALL SELECT 6)
INSERT Test
SELECT newid() 
FROM CTE a
CROSS JOIN CTE b
CROSS JOIN CTE c
CROSS JOIN CTE d
GO 5

Beginning execution loop

(1296 row(s) affected)

(1296 row(s) affected)

(1296 row(s) affected)

(1296 row(s) affected)

(1296 row(s) affected)

Batch execution completed 5 times.

Let’s see how fragmented the index is

SELECT Object_name(s.object_id) as Tablename,s.name as Indexname
,index_type_desc
,avg_fragmentation_in_percent
,page_count
FROM sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL , NULL, N'LIMITED') d
join sys.indexes s on d.object_id = s.object_id
and d.index_id = s.index_id
and s.name = 'ix_Test_bla'
Tablename  Indexname   index_type_desc avg_fragmentation_in_percent    page_count
Test            ix_Test_bla CLUSTERED INDEX 34.4827586206897                 58

Now it is time to ‘fix’ the index, we can either defragment/reorganize or rebuild the index

ALTER INDEX ix_Test_bla ON [dbo].[Test] REORGANIZE

_Msg 40517, Level 16, State 1, Line 1

Keyword or statement option ‘REORGANIZE’ is not supported in this version of SQL Server._

Okay, so SQL Azure does not support reorganizing the index

What if we drop the index and then create it again?

DROP INDEX [ix_Test_bla] ON [dbo].[Test] 
GO

_Msg 40054, Level 16, State 2, Line 1

Tables without a clustered index are not supported in this version of SQL Server. Please create a clustered index and try again.

The statement has been terminated._

Mmmm, not supported either, let’s try creating the index with the drop_existing clause

CREATE CLUSTERED INDEX [ix_Test_bla] ON [dbo].[Test]
(
	[bla] ASC
)WITH (DROP_EXISTING = ON)
GO

That worked, let’s check fragmentation again

SELECT Object_name(s.object_id) as Tablename,s.name as Indexname
,index_type_desc
,avg_fragmentation_in_percent
,page_count
FROM sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL , NULL, N'LIMITED') d
join sys.indexes s on d.object_id = s.object_id
and d.index_id = s.index_id
and s.name = 'ix_Test_bla'
Tablename  Indexname   index_type_desc avg_fragmentation_in_percent    page_count
Test            ix_Test_bla CLUSTERED INDEX 4.76190476190476                21

Mmmm, didn’t get rid of all the fragmentation. What happens if we try to do the same again?

CREATE CLUSTERED INDEX [ix_Test_bla] ON [dbo].[Test]
(
	[bla] ASC
)WITH (DROP_EXISTING = ON)
GO
SELECT Object_name(s.object_id) as Tablename,s.name as Indexname
,index_type_desc
,avg_fragmentation_in_percent
,page_count
FROM sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL , NULL, N'LIMITED') d
join sys.indexes s on d.object_id = s.object_id
and d.index_id = s.index_id
and s.name = 'ix_Test_bla'
Tablename  Indexname   index_type_desc avg_fragmentation_in_percent    page_count
Test            ix_Test_bla CLUSTERED INDEX 9.52380952380952                 21

Still didn’t get rid of all fragmentation

Let’s try something else, first we are going to add some more data

;WITH CTE AS (SELECT 1 AS A 
			UNION ALL SELECT 2 
			UNION ALL SELECT 3 
			UNION ALL SELECT 4 
			UNION ALL SELECT 5
			UNION ALL SELECT 6)
INSERT Test
SELECT newid() 
FROM CTE a
CROSS JOIN CTE b
CROSS JOIN CTE c
CROSS JOIN CTE d
go 5

Let’s check fragmentation

SELECT Object_name(s.object_id) as Tablename,s.name as Indexname
,index_type_desc
,avg_fragmentation_in_percent
,page_count
FROM sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL , NULL, N'LIMITED') d
join sys.indexes s on d.object_id = s.object_id
and d.index_id = s.index_id
and s.name = 'ix_Test_bla'
Tablename  Indexname   index_type_desc avg_fragmentation_in_percent    page_count
Test            ix_Test_bla CLUSTERED INDEX 72.8395061728395                 81

Oh yeah, that is real bad

Now let’s rebuild the index instead

ALTER INDEX ix_Test_bla ON [dbo].[Test] REBUILD

Check fragmentation again

SELECT Object_name(s.object_id) as Tablename,s.name as Indexname
,index_type_desc
,avg_fragmentation_in_percent
,page_count
FROM sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL , NULL, N'LIMITED') d
join sys.indexes s on d.object_id = s.object_id
and d.index_id = s.index_id
and s.name = 'ix_Test_bla'
Tablename  Indexname   index_type_desc avg_fragmentation_in_percent    page_count
Test            ix_Test_bla CLUSTERED INDEX 0                               41

And just like that all the fragmentation is gone…..good times