我最近一直在追踪客户数据库的一个问题...找到了解决方案,但无法重现。
本质上,我们正在做一个
Select * from mytable where ArbitraryColumn = 75
MyTable 中有一个标识列,称为“MyIndentityColumn” - 每次插入时都会增加 1。自然而然,通常我会假设返回的顺序是它们插入的顺序(错误的假设,但这是继承的应用程序强加给我的 - 已修补)。
本质上,我希望得到关于为什么当数据库恢复到我的本地计算机(相同的操作系统,相同的 SQL 服务器版本 - 200 sp3)相同的排序规则,并在其上恢复相同的备份实例时,作为客户端站点上的测试数据库的建议。
当我执行上述选择时,我会按插入顺序获取它们(即,标识列按升序排序)。在客户端上,它似乎是随机的(但每次都是相同的“随机”顺序)...
其他几点:
- 我的测试服务器上的排序规则与客户端相同
- 相同的数据库备份已恢复到只有我可以访问的测试
- 相同的 SQL Server 版本和服务包
- 相同的操作系统
- 测试数据库是一个新的数据库——新的日志和MDF......
我已经通过添加明确的 order by 子句“解决”了这个问题,但我想了解问题的原因,因为我尝试重新创建它是徒劳的,并且可以在客户端服务器上完美地重新创建......
提前致谢,
戴夫
答案1
确定记录集的顺序仅有的按最外层的 ORDER BY。
为免生疑问:没有默认排序顺序
你提到的“可重现”顺序只反映了 SQL Server 如何读取执行计划中的数据你的服务器那时间。相同的服务包?相同的版本?相同数量的 CPU(包括 HT)?完全相同的 SET 选项?
如果计划发生变化,顺序可能也会发生变化。它与插入顺序、索引顺序或磁盘位置顺序无关。
该问题来自 StackOverflow,之前已经得到过回答:
- https://stackoverflow.com/questions/1793147/sql-best-practice-to-deal-with-default-sort-order
- https://stackoverflow.com/questions/1707506/are-the-results-deterministic-if-i-partition-sql-select-query-without-order-by
- ETC
来自 MSDN,使用 ORDER BY 对行进行排序
ORDER BY 仅保证查询最外层的 SELECT 语句的排序结果。例如,考虑以下视图定义
SQL Server 查询优化器在计划选择中是否考虑索引碎片?
不,它并不直接关心。
答案2
返回记录的顺序取决于您的索引。有三件事在起作用:
- 查询中使用的索引是什么?您的标识列是索引的主要部分吗?
- 所用索引的碎片程度。如果碎片程度很高,则返回的记录肯定会乱序。
- 您正在使用的索引是该表上的聚集索引吗
保证返回记录顺序的唯一方法是使用 ORDER BY 语句。如果您依赖于返回记录集的特定顺序,那么您必须使用 ORDER BY 语句。
答案3
经过一番广泛调查,我们发现了路线问题......
客户的表上有额外的索引,这导致所有内容不同步,但仅限于他们的服务器上。在本地测试时,无论是备份 LDF/MDF 还是恢复到新数据库,都没有出现问题。
在客户端计算机上,在原始 mdf/mdf 上,在备份和恢复后,或在恢复到的新数据库上,该问题 100% 可靠地显示出来。
为了证明索引是原因,我们可以删除并重新添加索引,然后观察不良行为的发生,然后不再发生。