完美重现选择语句默认排序问题

完美重现选择语句默认排序问题

我最近一直在追踪客户数据库的一个问题...找到了解决方案,但无法重现。

本质上,我们正在做一个

Select * from mytable where ArbitraryColumn = 75

MyTable 中有一个标识列,称为“MyIndentityColumn” - 每次插入时都会增加 1。自然而然,通常我会假设返回的顺序是它们插入的顺序(错误的假设,但这是继承的应用程序强加给我的 - 已修补)。

本质上,我希望得到关于为什么当数据库恢复到我的本地计算机(相同的操作系统,相同的 SQL 服务器版本 - 200 sp3)相同的排序规则,并在其上恢复相同的备份实例时,作为客户端站点上的测试数据库的建议。

当我执行上述选择时,我会按插入顺序获取它们(即,标识列按升序排序)。在客户端上,它似乎是随机的(但每次都是相同的“随机”顺序)...

其他几点:

  1. 我的测试服务器上的排序规则与客户端相同
  2. 相同的数据库备份已恢复到只有我可以访问的测试
  3. 相同的 SQL Server 版本和服务包
  4. 相同的操作系统
  5. 测试数据库是一个新的数据库——新的日志和MDF......

我已经通过添加明确的 order by 子句“解决”了这个问题,但我想了解问题的原因,因为我尝试重新创建它是徒劳的,并且可以在客户端服务器上完美地重新创建......

提前致谢,

戴夫

答案1

确定记录集的顺序仅有的按最外层的 ORDER BY。

为免生疑问:没有默认排序顺序

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

如果计划发生变化,顺序可能也会发生变化。它与插入顺序、索引顺序或磁盘位置顺序无关。

该问题来自 StackOverflow,之前已经得到过回答:

来自 MSDN,使用 ORDER BY 对行进行排序

ORDER BY 仅保证查询最外层的 SELECT 语句的排序结果。例如,考虑以下视图定义

Conor 的博客

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

不,它并不直接关心。

答案2

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

  • 查询中使用的索引是什么?您的标识列是索引的主要部分吗?
  • 所用索引的碎片程度。如果碎片程度很高,则返回的记录肯定会乱序。
  • 您正在使用的索引是该表上的聚集索引吗

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

答案3

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

客户的表上有额外的索引,这导致所有内容不同步,但仅限于他们的服务器上。在本地测试时,无论是备份 LDF/MDF 还是恢复到新数据库,都没有出现问题。

在客户端计算机上,在原始 mdf/mdf 上,在备份和恢复后,或在恢复到的新数据库上,该问题 100% 可靠地显示出来。

为了证明索引是原因,我们可以删除并重新添加索引,然后观察不良行为的发生,然后不再发生。

相关内容