为什么表中的记录排序不是按聚簇索引?

时间:2016-05-26 12:10:58

标签: sql sql-server indexing primary-key clustered-index

我一直在准备面试,只是来这些事情。

我已执行以下声明:

create table trial
(
    Id int not null,
    Name varchar(10)
)

alter table trial add constraint unq unique clustered (Name)

alter table trial add constraint pk primary key nonclustered(Id)

insert into trial values (1,'a'),(3,'d'),(5,'b'),(2,'c')

select * from trial

结果如下所示:

enter image description here

我的问题是:为什么结果不按名称列排序,因为名称列具有聚集索引?

结果是:

1 a
2 c
3 d
5 b

如何使用索引对表进行物理排序?

2 个答案:

答案 0 :(得分:4)

重复:SQL表代表无序集。除非查询包含order by子句,否则SQL结果集无序

因此,如果您想按顺序获取数据,请使用order by

select t.*
from trial t
order by t.name;

如果您想要按特定顺序排列结果,请使用order by。 SQL Server有一个很好的优化器。如果它可以使用查询的索引 - 以避免实际排序 - 那么它通常会使用索引。

答案 1 :(得分:2)

在这种情况下,我确信优化器决定进行全表扫描或非聚簇索引扫描,因为它非常小。您可以包含实际执行计划并查看:

enter image description here

您可以强制使用聚集索引:

SELECT * FROM TRIAL WITH (INDEX(UNQ))

你可能会得到:

enter image description here

和结果集:

Id  Name
1   a
5   b
2   c
3   d

但你不应该这样做,因为订购仍然没有保证。如果您希望按某些列对结果进行排序,请明确执行此操作!

我会从书中Exam 70-461: Querying Microsoft SQL Server 2012复制一个片段,你可以在那里得到一些好的解释:

  

似乎输出按empid排序,但事实并非如此   保证。更令人困惑的是,如果你运行查询   反复地,似乎结果一直在返回   订购;但同样,这不能保证。当数据库引擎时(SQL   在这种情况下服务器)处理此查询,它知道它可以返回   任何顺序的数据,因为没有明确的指令   按特定顺序返回数据。可能是因为   优化和其他原因,SQL Server数据库引擎选择   这次以特定方式处理数据。甚至还有一些   如果是物理的话,这种选择会重复的可能性   情况保持不变。但是两者之间存在很大差异   由于优化和其他原因而可能发生的事情   什么是实际保证。

     

数据库引擎可能 - 有时也可能   更改选项可能会影响行的顺序   知道可以自由地回来了。这种变化的例子   在选择中包括数据分布的变化,可用性   物理结构,如索引和资源的可用性   像CPU和内存。此外,随着发动机的变化   升级到更新版本的产品,甚至是申请后   一个服务包,优化方面可能会改变。反过来,这样   除其他外,更改可能会影响行中的行的顺序   结果。

     

简而言之,这不足以强调:一个不的查询   有明确指示以特定顺序返回行   不保证结果中行的顺序。当你需要的时候   这样的保证,提供它的唯一方法是添加ORDER BY   查询的子句,这是下一节的重点。

根据评论编辑:

问题是,即使您使用聚簇索引,它也可能返回无序集。假设您具有像(1, 2, 3, 4, 5)这样的聚类键的物理顺序。大多数情况下,您会得到(1, 2, 3, 4, 5),但可能会出现优化程序决定执行并行读取并说它有2个并行读取且读取(1, 2, 3)和{{1 }}。现在可能会首先返回(4, 5),然后可以返回(4, 5)。如果您没有(1, 2, 3)子句,则引擎将不会花费其资源来订购该集合并将为您提供order by。这就解释了为什么在订购时应始终确保有(4, 5, 1, 2, 3)子句。