(Look in the Misconceptions blog category for the rest of the month’s posts and check out the 60-page PDF with all the myths and misconceptions blog posts collected together when you join our Insider list, plus my online Myths and Misconceptions training course on Pluralsight.)
Another quickie but goodie before the finale tomorrow!
Myth #29: fix heap fragmentation by creating and dropping a clustered index.
This is just about one of the worst things you could do outside of shrinking a database.
If you run sys.dm_db_index_physical_stats (or my old DBCC SHOWCONTIG) on a heap (a table without a clustered index) and it shows some fragmentation, don’t EVER create and drop a clustered index to build a nice, contiguous heap. Do yourself a favor and just create the well-chosen clustered index and leave it there – there’s a ton of info out there on choosing a good clustering key – narrow+static+unique+ever-increasing is what you need. Kimberly has a blog post from 2005(!) that sums things up: Ever-increasing clustering key – the Clustered Index Debate……….again! and I’ve got An example of a nasty cluster key.
Yes, you can use ALTER TABLE … REBUILD in SQL Server 2008+ to remove heap fragmentation, but that is almost as bad as creating and dropping a clustered index!
Why am I having a conniption fit about this? Well, every record in a nonclustered index has to link back to the matching row in the table (either a heap or clustered index – you can’t have both – see Kimberly’s recent SQL Server Magazine blog post What Happens if I Drop a Clustered Index? for an explanation). The link takes the form of:
- If the table is a heap, the actual physical location of the table record (data file:page number:record number)
- If the table has a clustered index, the clustering key(s)
The blog post link at the bottom of this post explains in a lot more detail.
If you create a clustered index, all the linkages to the heap records are no longer valid and so all the nonclustered indexes must be rebuilt automatically to pick up the new clustering key links. If you drop the clustered index again, all the clustering key links are now invalid so all the nonclustered indexes must be rebuilt automatically to pick up the new heap physical location links.
In other words, if you create and then drop a clustered index, all the nonclustered indexes are rebuilt twice. Nasty.
If you think you can use ALTER TABLE … REBUILD to fix heap fragmentation, you can, but it causes all the nonclustered indexes to be rebuilt as the heap record locations obviously change.
Now, what about if you *rebuild* a clustered index? Well, that depends on what version you’re on and whether you’re doing a simple rebuild or changing the definition of the index. One major point of misconception is that moving a clustered index or partitioning it changes the cluster keys – it doesn’t. For a full list of when the nonclustered indexes need to be rebuilt, see Indexes From Every Angle: What happens to non-clustered indexes when the table structure is changed?