我注意到,如果我有一个不包含列“Id”的表,并且您选择数据没有“ORDER BY”sql server不会自动排序在主列上.
有没有人知道什么规则sql server跟随来排序它的数据?
解决方法
不同的RDMBS-es行为不同,一个特定的实例可能由于更新(补丁)而有所不同.不仅如此,即使RDBMS软件的状态也可能产生影响:“温暖”数据库的行为与“冷”数据库的行为不同,小表的行为与大型表的行为不同.
即使你有关于实现的背景信息(例如:“有一个聚簇索引,因此很可能数据将通过聚簇索引的顺序返回”),总有一种可能性,有另外一种机制你不不知道会导致以不同的顺序返回行(ex1:“如果另一个会话刚刚执行了一个完整的表扫描,结果集中的显式ORDER可能已被缓存,则后续的全面扫描将尝试将行从缓存“; ex2:”可以通过对数据进行排序来实现GROUP BY,从而影响行的返回顺序“; ex3:”如果选定的列都在已经缓存在内存中的辅助索引中,引擎可以扫描辅助索引而不是表,最有可能按次序索引的顺序返回行“).
这是一个非常简单的测试,说明了我的一些观点.
首先,启动sql Server(我正在使用2008).创建此表:
create table test_order ( id int not null identity(1,1) primary key,name varchar(10) not null )
检查表并看到创建了一个聚簇索引以支持id列上的主键.例如,在sql server管理工作室中,您可以使用树视图并导航到表格下方的索引文件夹.你应该看到一个索引,名称如下:PK__test_ord__3213E83F03317E3D(集群)
用这个语句插入第一行:
insert into test_order(name) select RAND()
通过重复此语句插入更多行16次:
insert into test_order(name) select RAND() from test_order
您现在应该有65536行:
select COUNT(*) from test_order
现在,选择所有行,而不使用顺序:
select * from test_order
很可能,结果将按主键的顺序返回(尽管不能保证).这是我得到的结果(这是按主键的顺序):
# id name 1 1 0.605831 2 2 0.517251 3 3 0.52326 . . ....... 65536 65536 0.902214
(#不是列,而是结果中行的顺序位置)
现在,在名称列上创建一个辅助索引:
create index idx_name on test_order(name)
选择所有行,但仅检索名称列:
select name from test_order
最可能的结果将通过辅助索引idx_name的顺序返回,因为只能扫描索引才能解析查询(i.o.w. idx_name是覆盖索引).这是我得到的结果,这的确是按照名称的顺序.
# name 1 0.0185732 2 0.0185732 . ......... 65536 0.981894
现在,再次选择所有列和所有行:
select * from test_order
这是我得到的结果:
# id name 1 17 0.0185732 2 18 0.0185732 3 19 0.0185732 ... .. .........
正如你所看到的,与我们第一次运行这个查询完全不同. (它看起来像是由二级索引排序的行,但是我没有解释为什么这样).
无论如何,底线是 – 不要依赖隐含的顺序.您可以想到为什么可以观察到特定顺序的解释,但即使如此,您也不能总是预测它(如在后一种情况),而不需要对实现和运行时状态的深入了解.