Sql-Server

具有聚集索引的表按唯一非聚集索引隱式排序

  • May 7, 2020

我有一個表格,可以擷取使用者正在執行的主機平台。該表的定義很簡單:

IF OBJECT_ID('[Auth].[ActivityPlatform]', 'U') IS NULL
BEGIN
   CREATE TABLE [Auth].[ActivityPlatform] (
       [ActivityPlatformId] [tinyint] IDENTITY(1,1) NOT NULL
       ,[ActivityPlatformName] [varchar](32) NOT NULL
       ,CONSTRAINT [PK_ActivityPlatform] PRIMARY KEY CLUSTERED ([ActivityPlatformId] ASC)
       ,CONSTRAINT [UQ_ActivityPlatform_ActivityPlatformName] UNIQUE NONCLUSTERED ([ActivityPlatformName] ASC)
   ) ON [Auth];
END;
GO

它儲存的數據是基於使用來自其瀏覽器的資訊的 JavaScript 方法列舉的(我知道的不多,但如果需要,可以找到):

平台

但是,當我在SELECT沒有顯式的情況下執行基本ORDER BY操作時,執行計劃顯示它正在使用UNIQUE NONCLUSTERED索引而不是索引進行排序CLUSTERED

SELECT * FROM [Auth].[ActivityPlatform] 

非集群記憶體

當明確指定 時ORDER BY,它正確地按 排序ActivityPlatformId

SELECT * FROM [Auth].[ActivityPlatform] ORDER BY [ActivityPlatformId]

集群記憶體

DBCC SHOWCONTIG('[Auth].[ActivityPlatform]') WITH ALL_LEVELS, TABLERESULTS顯示沒有表碎片。

我錯過了什麼可能導致這種情況?我想了很久,表是在聚集索引上創建的,它應該自動隱式排序,而不需要指定ORDER BY. SQL Server 在選擇 UQ 時的偏好是什麼?我需要在表的創建中指定什麼嗎?

不,排序不是隱含的,不應依賴。事實上,在第一個工具提示中,您可以看到它明確指出Ordered = False. 這意味著 SQL Server 根本沒有做任何事情來實現任何排序。你觀察到的只是它發生的事情,而不是它試圖做的事情。

如果您希望能夠預測可靠的排序順序,請輸入ORDER BY. 時期。當您添加時您可能會觀察到的內容ORDER BY可能很有趣,但不能依賴它來保持一致。事實上,在這篇文章中,參見#3,我展示了查詢的輸出如何通過其他人添加索引而發生變化。

SQL Server 在選擇 UQ 時的偏好是什麼?

索引包含集群鍵,因此UNIQUE NONCLUSTERED它覆蓋了查詢。在這種情況下,您的表只有兩列,因此聚集索引和非聚集索引包含相同的數據(只是排序不同)。它們的大小相同,因此優化器可以選擇其中一個。它選擇非聚集索引是一個實現細節。

我稱之為“拋硬幣”。

引用自:https://dba.stackexchange.com/questions/201678