views:

588

answers:

6

I have inherited a database where there are clustered indexes and additional duplicate indexes for each of the clustered index.

i.e IX_PrimaryKey is a clustered index on the column ID. IX_ID is a non clustered index on the column ID.

I want to clean up these duplicate non clustered indexes and I wanted to check to see if anyone could think of a reason to do this.

Can anyone think of a performance benefit for doing this?

+1  A: 

For exact same indexes, there's no performance gain. Actually, it incurs performance loss in insertion and updates. However, if there are multicolumn indexes with different column order, there might be a valid reason for them.

Mehrdad Afshari
A: 

Maybe I'm not thinking hard enough, but I can't see any reason to do this; the nature of the clustered index is that the data is organized in the order of the index. It seems that the extra index is a complete waste.

Digging through BOL and watching this question, though ...

Adrien
A: 

There seems no sensible reason for doing this, and there is a performance hit.

The only thing I could think of to do this is to create an index with an incredibly narrow row width so that the rows per page was very high, making it very quick to scan / seek. But since it contains no other fields (except the clustered key, which is the same value) I still cannot see a reason for it.

It's quite possible the original creator was not aware that the PK was defaulting to a clustered index and created an NC index without realising it was a duplicate.

Andrew
A: 

Hi

I presume what would have happened is that SQL Server would have automatically created clustered index when a primary key constraint was specified (this would happen if another index (non-clustered/clustered) is not present already) and then some one might have created a non-clustered index for the primary key column.

Such a scenario would:

  • Have some adverse effect on performance as indexes are updated when inserts/deletes/updates happen.
  • Use additional disk space.
  • Might lead to deadlocks.
  • Would contribute to more time in backup/restore of database.

cheers

Andriyev
A: 

It will be a waste to create a clustered primary key. Unless you have query that search for records using WHERE ID = 10 ?

You may want to create a clustered index on the column which will be frequently queried on WHERE City = 'Sydney'. Clustered means that SQL will group the data in the table based on the clustered index. By grouping the City values in the table means SQL can search for data quicker.

tnafoo
A: 

Storing two indexes over the same data is a waste of disk space and the processing needed to maintain the data.

However, I can imagine a product which depends on the existence of an index named IX_PrimaryKey. E.G.

string queryPattern = "select * from {0} as t with (index(IX_PrimaryKey))";

You can make the argument that the clustered index itself occupies much less space than the others, since the leaf is the actual data. On the other hand, the clustered index can be more susceptible to page splitting, and some indexes are better non-clustered.

Putting this together, I can definitely think of scenarios where removing the duplicate indexes would be a Bad Thing:

  • Code like above which depends on a known index name.
  • Code which can alter the clustered index to any of the non-clustered indexes.
  • Code which uses the presence/absence of IX_PrimaryKey to treat the table in a certain way.

I don't consider any of these good design, but I can definitely imagine someone doing it. (Have you posted this to DailyWTF?)

There are cases where it makes sense to have overlapping indexes which are not identical:

create index IX_1 on table1 (ID)
create index IX_2 on table1 (ID, TYPE, ORDER_DATE, TOTAL_CHARGES)

If you are looking up strictly by ID, SQL can optimize and use IX_1. If you are running a query based on ID, TYPE, ORDER_DATE and summing up TOTAL_CHARGES, SQL can use IX_2 as a "covering index", satisfying all the query details from the index without ever touching the table. Generally this is something you add in the course of performance tuning, after extensive testing.

Looking at your given example of two indexes on exactly the same field, I don't see a great fit. Perhaps SQL can use IX_ID as a "covering index" when checking for the existence of a value and bypass some blocking on IX_PrimaryKey?

Bruce
I had thought of DailyWTF but I thought that might be a bit mean...:)
GordyII