我有一个表,用于捕获用户正在运行的主机平台。该表的定义很简单:
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,我展示了如何通过其他人添加索引来简单地更改查询的输出。索引包含聚
UNIQUE NONCLUSTERED
簇键,因此它覆盖了查询。在这种情况下,您的表只有两列,因此聚簇索引和非聚簇索引包含相同的数据(只是排序不同)。它们的大小相同,因此优化器可以选择其中一个。它选择非聚集索引是一个实现细节。我称之为“抛硬币”。