sql server如何对数据进行排序?

10 select sql-order-by sql-server-2008

我想知道sql server如何对它的数据进行排序.我注意到,如果我有一个不包含列"Id"的表,并且您选择没有"ORDER BY"的数据,则sql server不会自动对主列进行排序.

有谁知道sql server遵循什么规则来排序它的数据?

Rol*_*man 20

虽然我们很想知道如何解释你经常会看到相同的顺序,但我想指出依赖于底层数据库引擎的特定实现导致的隐式顺序绝不是一个好主意.换句话说,很高兴知道为什么,但你永远不应该依赖它.对于MS SQL,唯一能够以特定顺序可靠地传递行的是一个显式ORDER BY子句.

不仅不同的RDMBS-es表现不同,一个特定实例可能由于更新(补丁)而表现不同.不仅如此,即使RDBMS软件的状态也可能产生影响:"热"数据库的行为与"冷"数据库不同,小表的行为与大表不同.

即使你有关于实现的背景信息(例如:"有聚集索引,因此很可能数据将按聚集索引的顺序返回"),总有可能存在另一种机制.知道这会导致行以不同的顺序返回(ex1:"如果另一个会话刚刚进行了全表扫描,显式ORDER BY结果集可能已被缓存;后续的完整扫描将尝试从缓存中返回行"; ex2:"a GROUP BY可以通过对数据进行排序来实现,从而影响行返回的顺序"; ex3:"如果所选列都在已经缓存在内存中的二级索引中,则引擎可以扫描辅助索引而不是表,最有可能按二级索引的顺序返回行").

这是一个非常简单的测试,说明了我的一些观点.

首先,启动SQL服务器(我正在使用2008).创建此表:

create table test_order (
    id int not null identity(1,1) primary key
,   name varchar(10) not null 
)
Run Code Online (Sandbox Code Playgroud)

检查一个clusted指数的设立是为了支持表和见证primary keyid列.例如,在sql server management studio中,您可以使用树视图并导航到表下方的索引文件夹.你应该看到一个索引,名称如下:PK__test_ord__3213E83F03317E3D (Clustered)

使用以下语句插入第一行:

insert into test_order(name)
select RAND()
Run Code Online (Sandbox Code Playgroud)

通过重复此语句16次插入更多行:

insert into test_order(name)
select RAND()
from   test_order
Run Code Online (Sandbox Code Playgroud)

您现在应该有65536行:

select COUNT(*) 
from   test_order
Run Code Online (Sandbox Code Playgroud)

现在,选择所有行而不使用订单:

select *
from   test_order
Run Code Online (Sandbox Code Playgroud)

最有可能的是,结果将按主键的顺序返回(尽管不能保证).这是我得到的结果(实际上是按主键的顺序):

#      id    name
1      1     0.605831
2      2     0.517251
3      3     0.52326
.      .     .......
65536  65536 0.902214
Run Code Online (Sandbox Code Playgroud)

(#不是列,而是结果中行的序号位置)

现在,在name列上创建一个二级索引:

create index idx_name on test_order(name)
Run Code Online (Sandbox Code Playgroud)

选择所有行,但仅检索name列:

select name
from   test_order
Run Code Online (Sandbox Code Playgroud)

最有可能的结果将按二级索引idx_name的顺序返回,因为只能通过扫描索引来解析查询(iow idx_name覆盖索引).这是我得到的结果,这确实是按顺序排列的name.

#      name
1      0.0185732
2      0.0185732
.      .........
65536  0.981894
Run Code Online (Sandbox Code Playgroud)

现在,再次选择所有列和所有行:

select * 
from test_order
Run Code Online (Sandbox Code Playgroud)

这是我得到的结果:

#      id    name
1      17    0.0185732
2      18    0.0185732
3      19    0.0185732
...    ..    .........
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,与我们第一次运行此查询时有很大不同.(看起来这些行是由二级索引排序的,但我没有解释为什么会这样).

无论如何,底线是 - 不要依赖隐含的顺序.您可以考虑解释为什么可以观察到特定的顺序,但即使这样,您也不能总是预测它(如后一种情况),而不必熟悉实现和运行时状态.