Thursday, September 8, 2016

Sql Server - Finding Duplicate Indexes


If you are reading this article, I assume that you have basic knowledge of Index, its types and usage.
Over the years of development and chasing high performance we build and update many indexes. Due to shear number or complexity for forget to keep track of number, quantity and utilization of the indexes.

Let’s get back to present; now our application is working fine and our Project Manager comes and says “Guys it time for cleanup”. He means find out the unused and duplicate index and remove them. Why , because good indexing provides good performance and poor implementation of indexing results in poor performance. Pretty straight forward.  

As I mentioned above for index utilization we have a separate article (Index Utilization Report).
So let’s focus on duplicate index. First question is how we will decide two indexes are identical or duplicate.

Here I am using a very simple concept, if two indexes are using the same columns (Table.Column) irrespective of their order and index type (Clustered or Non Clustered) are considered duplicate.
For testing purpose I have created three duplicate indexes, marked in Yellow, Orange and Green.



Case Yellow Here both indexes are of same type non clustered and same column only their names are different, so basically both of them are same index hence duplicate.

Case Orange – Both indexes are using the same column but they are different kind (one is clustered and other is non clustered) and different name. So as per our logic both index are using same columns so they are duplicate.

Case Green – Here we have same set of columns but in different order and index types are different.  So as per our logic both indexes are duplicate, even though columns order and index types are same.  

Here is the script to gather the information for analysis, you may have different criteria to decide the duplicity. So feel free to modify the script or use the power of MS excels. If you need my help drop a comment and I will try my best to help you.

Begin

Create Table #AllIndex
(
TableName varchar(256),
TableType varchar(256),
IndexName varchar(256),
IndexType varchar(256),
IndexId int
)

insert into #AllIndex
select Distinct
O.name As 'TableName',
O.type_desc As 'TableType',
I.name As 'IndexName',
I.type_desc As 'IndexType',
I.index_id As 'IndexId'
FROM sys.indexes I
INNER JOIN sys.objects O ON I.[object_id] = O.[object_id]
INNER JOIN sys.schemas S ON S.[schema_id] = O.[schema_id]
WHERE index_id > 0 and (O.type_desc='USER_TABLE' or O.type_desc='VIEW')



Select T.TableType,T.IndexId,T.TableName,T.IndexName,
INDEX_COL('dbo' + '.' +T.TableName, T.IndexId, 1) as 'ColumnName1',
INDEX_COL('dbo' + '.' +T.TableName, T.IndexId, 2) as 'ColumnName2',
INDEX_COL('dbo' + '.' +T.TableName, T.IndexId, 3) as 'ColumnName3',
INDEX_COL('dbo' + '.' +T.TableName, T.IndexId, 4) as 'ColumnName4',
INDEX_COL('dbo' + '.' +T.TableName, T.IndexId, 5) as 'ColumnName5',
INDEX_COL('dbo' + '.' +T.TableName, T.IndexId, 6) as 'ColumnName6',
INDEX_COL('dbo' + '.' +T.TableName, T.IndexId, 7) as 'ColumnName7',
INDEX_COL('dbo' + '.' +T.TableName, T.IndexId, 8) as 'ColumnName8',
INDEX_COL('dbo' + '.' +T.TableName, T.IndexId, 9) as 'ColumnName9',
INDEX_COL('dbo' + '.' +T.TableName, T.IndexId, 10) as 'ColumnName10'

/* If you have more than 10 columns in your indexes then add this
INDEX_COL('dbo' + '.' +T.TableName, T.IndexId, @Count) as 'ColumnName@Count',
and replcase the @Count with next number. */

From #AllIndex T
Order By T.TableName,T.IndexName,ColumnName1,ColumnName2,ColumnName3,ColumnName4,ColumnName5


Drop Table #AllIndex
End

Once you are ready with the list of duplicate index, you are ready to delete them. Here is the syntax to delete an index –
USE [YourDatabaseName]
GO
ALTER TABLE [dbo].[YourTableName] DROP CONSTRAINT [IndexName]
GO

Please note before deleting, do not delete Primary Key and clustered index. First delete non clustered index because non clustered index are build on clustered index. So do some research if you are not sure about the reason before taking any action.

Thanks & Cheers
Please provide your feedback for continuous improvement.