SELECT查询中的默认行顺序 - SQL Server 2008 vs SQL 2012

Cha*_*nns 12 sql sql-server database-migration sql-server-2008 sql-server-2012

我们的团队最近将我们的数据库从SQL Server 2008升级到SQL Server 2012.我们注意到的一个重大变化是SELECT语句返回的行的默认顺序,即未指定显式ORDER BY子句时.

根据MSDN,除非指定了ORDER BY子句,否则SQL Server 2012不会保证返回的行的顺序.

我们在5个数据库中有2500多个存储过程,这些数据库具有没有ORDER BY子句的SELECT语句,并且手动添加ORDER BY子句以匹配SQL Server 2008中的行为将是一项相当大的工作.是否有设置或更快的方法这个?

另一个尚未探索的选项是降级到SQL Server 2008.这有多难?

Mik*_* D. 42

您需要返回并ORDER BY在代码中添加子句,因为没有它们,订单永远不会得到保证.你过去"幸运",你总是得到相同的订单但不是因为SQL Server 2008无论如何都保证了它.它很可能与您的索引或数据如何存储在磁盘上有关.

如果在升级时移动到新主机,则硬件配置的差异可能会改变查询的执行方式.更不用说新服务器将重新计算表的统计信息,而SQL Server 2012查询优化器的功能可能与SQL Server 2008中的不同.

这是一个谬论,你可以依赖SQL中结果集的顺序,而无需明确说明你想要它的顺序.SQL结果永远不会有一个你可以依赖的顺序而不使用ORDER BY子句.SQL是围绕集合论构建的.查询结果基本上是集(或多集).

Itzik Ben-Gan在他的书" Microsoft SQL Server 2012 T-SQL Fundamentals"中对SQL的集合理论进行了很好的描述

源于数学家Georg Cantor的集合论是关系模型所依据的数学分支之一.康托尔对一组的定义如下:

通过"集合",我们指的是任何集合M到我们的感知或我们的思想的整个明确的,不同的对象m(被称为M的"元素")中. - Joseph W. Dauben和Georg Cantor(普林斯顿大学出版社,1990年)

在对Itzik定义中的术语进行彻底解释后,接着说:

康托尔对一组的定义遗漏了可能与它所包含的内容同样重要.请注意,该定义未提及集合元素中的任何顺序.列出集合元素的顺序并不重要.列表集元素的正式表示法使用大括号:{a,b,c}.由于订单没有相关性,因此您可以表达与{b,a,c}或{b,c,a}相同的集合.跳转到组成关系头的属性集(在SQL中称为列)(在SQL中称为表),应该通过名称来识别元素 - 而不是序数位置.类似地,考虑组成关系主体的元组集(称为SQL的行); 元素由其键值标识 - 而不是按位置标识.许多程序员很难适应这样的想法:对于查询表,行之间没有顺序.换句话说,对表的查询可以按任何顺序返回行,除非您明确请求以特定方式对数据进行排序,可能是出于演示目的.

但是无论一个集合的学术定义,即使SQL服务器中的实现也从未保证结果中的任何顺序.这从2005年MSDN博客文章查询优化小组的成员指出,你不应该依赖从中间业务在所有的顺序.

重新排序规则可能并且将违反此假设(并且当您对开发人员不方便时这样做).请理解,当我们重新排序操作以找到更有效的计划时,我们可以使树的中间节点的排序行为发生变化.如果您在树中放置了一个假定特定中间排序的操作,它可能会中断.

Conor Cunningham(架构师,SQL Server核心引擎)的这篇博客文章" 没有安全带 - 没有ORDER BY的期望订单 "是关于SQL Server 2008的.他有一个包含20k行的表,其中有一个索引似乎始终返回行相同的订单.添加ORDER BY查询甚至不会更改执行计划,因此如果优化程序意识到它不需要它,那么添加一个就不会使查询更加昂贵.但是,一旦他向表中添加了另外20k行突然查询计划发生了变化,现在它使用了并行性,结果不再有序!

这里最难的部分是任何外部用户都没有合理的方法知道计划何时会发生变化.所有计划的空间都很庞大,让人头脑发抖.如果有足够的参数更改,SQL Server的优化器将更改计划,即使对于简单查询也是如此.您可能会幸运,没有计划更改,或者您可以不考虑此问题并添加ORDER BY.

如果您需要更有说服力,请阅读以下帖子:

  • 我不知道您在使用表索引的简单查询以您期望的顺序返回行的事实中看到了什么.不,我在哪里说它永远不会按照你期望的顺序出现.重读我的答案中的一个SQL Server Architects的最后一个引用.如果没有`ORDER BY`子句,结果集的顺序可能会随时发生变化,原因很多,您无法知道它何时会发生.你所说的是糟糕的建议,不应该在生产系统中使用它.不要依赖索引进行排序.如果需要有序的结果集,请使用"ORDER BY" (2认同)
  • @Davos:删除了我的评论.订购条款必须100%准确. (2认同)