As with anything you do to a database you run your business on, backups should be made and care taken to ensure that you have a recovery plan if you unintentionally remove something you shouldn't have.  For example, you should never remove any unique index as the ERP vendor may be using this to enforce database integrity.  Thanks for visiting the site and I hope this helps!

Unnecessary Indexes

You can run additional queries to identify indexes that you could easily do without, even if occasionally used.  The following query will return indexes where the first column is identical.  Typically, you would want to keep the index that has the left most column and additional columns as the one with less columns is a subset of the other and the information is redundant.  This query can be run in SQL Server Management Studio or if your ERP program provides one, a query window. 

Having the proper indexes in place in a relational database is important to ensure that you get the performance you are expecting.  Having too many can ultimately have the reverse effect.  SQL Server starting with SQL 2005 keeps track of which ones don't get used in it's Dynamic Management Views.  The information kept in some of these views is reset when you alter the schema of a table and it is all reset when you restart SQL Server, so using these to identify the unused indexes is best done after the server has been up for an extended period of time.  The following query can be run in the SQL Server Management studio, or if your ERP program provides one, a query window.  It lists all the indexes not used that have been updated since the DMV for that index was reset.

Begin
select
    s.Name + N'.' + t.name as [Table]
    ,i1.index_id as [Index1 ID], i1.name as [Index1 Name]
    ,dupIdx.index_id as [Index2 ID], dupIdx.name as [Index2 Name] 
    ,c.name as [Column]
from 
    sys.tables t join sys.indexes i1 on
        t.object_id = i1.object_id
    join sys.index_columns ic1 on
        ic1.object_id = i1.object_id and
        ic1.index_id = i1.index_id and 
        ic1.index_column_id = 1  
    join sys.columns c on
        c.object_id = ic1.object_id and
        c.column_id = ic1.column_id      
    join sys.schemas s on 
        t.schema_id = s.schema_id
    cross apply
    (
        select i2.index_id, i2.name
        from
            sys.indexes i2 join sys.index_columns ic2 on       
                ic2.object_id = i2.object_id and
                ic2.index_id = i2.index_id and 
                ic2.index_column_id = 1  
        where    
            i2.object_id = i1.object_id and 
            i2.index_id > i1.index_id and 
            ic2.column_id = ic1.column_id
    ) dupIdx     
order by
    s.name, t.name, i1.index_id
    End




Begin
SELECT TOP 1
        DatabaseName = DB_NAME()
        ,TableName = OBJECT_NAME(s.[object_id])
        ,IndexName = i.name
        ,user_updates    
        ,system_updates    
INTO #TempUnusedIndexes
FROM   sys.dm_db_index_usage_stats s 
INNER JOIN sys.indexes i ON  s.[object_id] = i.[object_id] 
    AND s.index_id = i.index_id 
WHERE  s.database_id = DB_ID()
    AND OBJECTPROPERTY(s.[object_id], 'IsMsShipped') = 0
    AND    user_seeks = 0
    AND user_scans = 0 
    AND user_lookups = 0
    AND s.[object_id] = -999;

EXEC sp_MSForEachDB    'USE [?]; 
INSERT INTO #TempUnusedIndexes 
SELECT     
        DatabaseName = DB_NAME()
        ,TableName = OBJECT_NAME(s.[object_id])
        ,IndexName = i.name
        ,user_updates    
        ,system_updates    
FROM   sys.dm_db_index_usage_stats s 
INNER JOIN sys.indexes i ON  s.[object_id] = i.[object_id] 
    AND s.index_id = i.index_id 
WHERE  s.database_id = DB_ID()
    AND OBJECTPROPERTY(s.[object_id], ''IsMsShipped'') = 0
    AND    user_seeks = 0
    AND user_scans = 0 
    AND user_lookups = 0
    AND i.name IS NOT NULL and i.is_Unique = 0
    ORDER BY user_updates DESC;'

SELECT * FROM #TempUnusedIndexes ORDER BY [user_updates]  DESC
DROP TABLE #TempUnusedIndexes
End