Index
唯一索引與“非空”約束相結合是否等同於 PK 約束?
我有這些舊表定義(來自這裡):
CREATE TABLE [dbo].[JobItems] ( [ItemId] UNIQUEIDENTIFIER NOT NULL, -- lots of other columns CONSTRAINT [PrimaryKey_GUID_HERE] PRIMARY KEY NONCLUSTERED ([ItemId] ASC) ); CREATE UNIQUE CLUSTERED INDEX [JobItemsIndex] ON [dbo].[JobItems]([ItemId] ASC);
這有效地產生了兩個相同的索引。我想擺脫其中一個以減少插入時間並釋放磁碟空間。
該表儲存在生產 SQL Azure 數據庫中,因此我無法重建該表,也無法刪除聚集索引(SQL Azure 要求每個表都有一個聚集索引)。
我的要求是保留原始定義提供的所有數據完整性保證,並擺脫非聚集索引。看起來有一個
NOT NULL
約束和一個唯一索引讓我得到與 PK 約束相同的保證。所以 PK 約束是多餘的,我可以刪除它和基礎索引。我可以在這裡放棄 PK 約束而不期望有任何破壞嗎?
這有效地產生了兩個相同的索引。
索引不相同。CI 包括所有其他列,而 PK 在葉子上只有 ItemId 鍵列。所以聚集索引可能是非聚集索引大小的 100 倍。
例如,僅使用聚集索引的 COUNT(*) 和分頁查詢將顯著增加成本,因為它們必須使用表掃描。
現在,您的唯一索引和 PK 都唯一標識每一行。這是多餘的。可以刪除索引,並且可以將集群移動到 PK 中。但是,如果 ItemId 上有外鍵,它將失敗。
首先查找外鍵:
Select OBJECT_NAME(constraint_object_id) From sys.foreign_key_columns where referenced_object_id = OBJECT_ID('dbo.JobItems') and COL_NAME(referenced_object_id, referenced_column_id) = 'ItemId'
然後只需刪除它們(索引 + PK)並重新創建一個集群 PK:
If Exists(Select 1 From sys.indexes Where object_id = OBJECT_ID('dbo.JobItems') and name = 'JobItemsIndex') Begin Drop Index [JobItemsIndex] On [dbo].[JobItems] End If Exists(Select 1 From sys.indexes Where object_id = OBJECT_ID('dbo.JobItems') and name = 'PrimaryKey_GUID_HERE') Begin Alter Table [dbo].[JobItems] Drop Constraint [PrimaryKey_GUID_HERE] End Alter Table [dbo].[JobItems] Add Constraint [PrimaryKey_GUID_HERE] PRIMARY KEY CLUSTERED ([ItemId] ASC)