誤區 #29:可以通過對堆建叢集索引再DROP後進行堆上的磁碟重組
Nooooooooooooo!!!
對堆建叢集索引再DROP在我看來是除了收縮資料庫之外最2的事了。
如果你通過sys.dm_db_index_physical_stats(或是老版本的DBCC SHOWCONTIG)看到堆上有片段,絕對不要通過建立叢集索引再刪除叢集索引來整理堆片段。好的做法應該是建立叢集索引之後不再刪除,已經有非常多的資料闡述如何選擇一個理想的叢集索引鍵--窄,很少變動,唯一,自增。Kimberly有一篇文章對此做了一個總結:Ever-increasing clustering key - the Clustered Index Debate..........again!(注意,是基於SQL Server 2005版本),對此我也有一個例子:An example of a nasty cluster key。
你也可以在SQL Server 2008中通過ALTER TABLE ... REBUILD來清除堆片段,但這個做法和建立叢集索引後再刪除同樣邪惡。
如果你想問為什麼我對此甚有成見?好吧,那我解釋一下:非叢集索引中每一行都會指向一個RID或是叢集索引鍵的連結(詳情請看:What Happens if I Drop a Clustered Index?),這個連結會以下面兩種方式之一出現:
- 如果非叢集索引所在的表是堆,那麼這個連結就是一個RID。
- 如果非叢集索引所在的表是叢集索引,那麼這個連結就是叢集索引鍵。
如果你希望對此有更多瞭解,請看文章底部的連結。
因此不難看出,如果你希望將堆變為叢集索引,那麼非叢集索引的所有RID就失效了,因此所有的非叢集索引都需要被重建。同樣,如果刪除叢集索引鍵,那麼所有非叢集索引上儲存的叢集索引鍵都會失效,因此也需要重建所有的非叢集索引。
簡單點說,如果你建立再刪除叢集索引後,所有的非叢集索引都會被重建兩次。
如果你使用SQL Server 2008的ALTER TABLE ... REBUILD來整理堆片段,那麼同樣也需要重建所有的非叢集索引,因為所有的RID都會變動。
那麼,如果對於“重建”叢集索引呢?這取決於SQL Server的版本以及你是進行rebuild索引亦或是改變索引。一個常見的誤區是對錶進行分區將會改變叢集索引鍵,但事實上不會。對於那些會引起非叢集索引重建的操作,請看如下列表:Indexes From Every Angle: What happens to non-clustered indexes when the table structure is changed?。