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

Pic*_*llo 4 performance index sql-server execution-plan query-performance

我有一个表,用于捕获用户正在运行的主机平台。该表的定义很简单:

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
Run Code Online (Sandbox Code Playgroud)

它存储的数据是基于 JavaScript 方法枚举的,该方法使用来自浏览器的信息(我不知道更多,但可以在需要时找到):

平台

但是,当我在SELECT没有显式的情况下执行基本操作ORDER BY时,执行计划显示它正在使用UNIQUE NONCLUSTERED索引而不是CLUSTERED索引进行排序。

SELECT * FROM [Auth].[ActivityPlatform] 
Run Code Online (Sandbox Code Playgroud)

非集群缓存

当显式指定 时ORDER BY,它正确地按 排序ActivityPlatformId

SELECT * FROM [Auth].[ActivityPlatform] ORDER BY [ActivityPlatformId]
Run Code Online (Sandbox Code Playgroud)

集群缓存

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

我错过了什么可能导致这个?我一直认为该表是在聚集索引上创建的,它应该自动隐式地对其进行排序,而无需指定ORDER BY. SQL Server 在选择 UQ 时的偏好是什么?我需要在表的创建中指定什么吗?

Aar*_*and 14

不,排序不是隐含的,不应依赖。事实上,在第一个工具提示中,您可以看到它明确指出Ordered = False. 这意味着 SQL Server 根本没有做任何事情来实现任何排序。你观察到的只是它发生了什么,而不是它试图做什么。

如果您希望能够预测可靠的排序顺序,请输入ORDER BY. 时期。添加时可能会观察到的内容ORDER BY可能很有趣,但不能依靠它来保持一致的行为。事实上,在这篇文章中,请参阅 #3,我展示了如何通过其他人添加索引来更改查询的输出。

SQL Server 在选择 UQ 时的偏好是什么?

UNIQUE NONCLUSTERED指数包含聚集键,所以它覆盖了查询。在这种情况下,您的表只有两列,因此聚集索引和非聚集索引包含相同的数据(只是排序不同)。它们的大小相同,因此优化器可以选择其中之一。它选择非聚集索引是一个实现细节。

我称之为“抛硬币”。