完美再现select语句默认sorting问题

我最近一直在追查一个客户的数据库…解决scheme的问题,但不可能重新创build。

本质上,我们正在做一个

Select * from mytable where ArbitraryColumn = 75 

其中MyTable有一个名为“MyIndentityColumn”的标识列 – 在每个插入中增加一个。 当然,我通常会假定返回的顺序是它们被插入的顺序(错误的假设,但是通过inheritance的应用程序(已经被修补),这个假设被强加到我的头上)。

本质上,我想build议为什么当数据库恢复到我的本地机器(相同的操作系统,相同的SQL服务器版本 – 200 sp3)相同的sorting规则和相同的备份实例恢复它作为客户端站点上的testing数据库。

当我执行上面的select时,我按照插入的顺序(即标识列按顺序升序)得到它们。 在客户端,它似乎是随机的(但每次相同的“随机”顺序)…

其他几点:

  1. 我在客户端的testing服务器上使用相同的sorting规则
  2. 相同的数据库备份恢复到只有我可以访问的testing
  3. 相同的SQL服务器版本和服务包
  4. 同一操作系统
  5. testing数据库是一个新的数据库 – 新的日志和MDF …

我已经通过添加一个明确的order by子句来解决问题,但是我想要解决问题的原因,因为我尝试重新创build它的确切性质是徒劳无益的,并且可以在客户端服务器上完美地重新调用。

提前致谢,

戴夫

logging集的sorting由最外面的ORDER BY决定。

为了避免疑问: 没有默认的sorting顺序

您提到的“可重现”顺序只反映了SQL Server如何在当时服务器执行计划中读取数据。 相同的服务包? 同一版本? 相同数量的CPU(包括HT)? 完全一样的SET选项?

如果计划改变,订单也可能改变。 它与插入顺序或索引顺序或磁盘位置顺序无关。

这个问题属于StackOverflow并已被回答之前:

从MSDN, 用ORDER BYsorting行

ORDER BY只保证查询的最外层SELECT语句的sorting结果。 例如,考虑下面的视图定义

从Conor的博客 ,

SQL Server查询优化器是否在计划select中考虑索引碎片?

不,它不直接关心。

logging返回的顺序取决于您的索引。 有三件事情起作用:

  • 在查询中使用的索引是什么,并且是您的标识列是索引的主要部分。
  • 如何使用索引碎片。 如果它是高度分散的,那么logging肯定会被无序地退回。
  • 是在该表上使用聚簇索引的索引

保证返回logging顺序的唯一方法是使用ORDER BY语句。 如果您依赖于返回logging集的特定顺序,则必须使用ORDER BY语句。

经过一番广泛的调查,我们发现了路线问题…

客户端在桌面上有一个额外的索引,每个索引都不同步,但只在他们的服务器上。 在本地进行testing时,要么是LDF / MDF的备份,要么是恢复到新的数据库 – 问题没有展现出来。

在客户端机器上,在原始的mdf / mdf上,在备份和恢复之后,或者在恢复的新数据库上,问​​题100%可靠地展现。

作为索引是原因的证据,我们可以删除并重新添加索引,并查看不想要的行为发生,然后不会发生。