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

时间:2014-10-07 12:45:40

标签: sql sql-server sql-server-2008 sql-server-2012 database-migration

我们的团队最近将我们的数据库从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.这有多难?

1 个答案:

答案 0 :(得分:41)

您需要返回并在代码中添加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的集合论是   关系模型所依据的数学分支之一   根据。康托尔对一组的定义如下:

     

通过" set"我们的意思是任何集合M变成一个明确的,明确的   我们的感知或对象m(被称为"元素" M)   我们的想法。 - Joseph W. Dauben和Georg Cantor(普林斯顿大学)   大学出版社,1990年)

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

  

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

但是无论一个集合的学术定义,即使SQL服务器中的实现也从未保证结果中的任何顺序。这个MSDN blog post from 2005 by a member of the query optimizer team表明你根本不应该依赖中间操作的顺序。

  

重新排序规则可以并且将违反这一假设(并且这样做   当你不方便时,开发商;)。敬请谅解   当我们重新排序操作以找到更有效的计划时,我们可以   导致排序行为改变为中间节点   树。如果你在树中假定一个操作   特别是中间排序,它可以打破。

这篇由Conor Cunningham撰写的博客文章(建筑师,SQL Server核心引擎)" No Seatbelt - Expecting Order without ORDER BY"是关于SQL Server 2008.他有一个包含20k行的表,其中一个索引似乎始终以相同的顺序返回行。在查询中添加ORDER BY甚至不会更改执行计划,因此如果优化程序意识到它并不需要,那么添加一个就不会使查询更加昂贵。但是,一旦他再向表中添加了20k行,查询计划就会发生变化,现在它使用并行性,结果不再有序!

  

这里最难的部分是任何外部都没有合理的方法   用户知道计划何时会发生变化。所有计划的空间都很大   并且伤到你的思考。 SQL Server的优化器将发生变化   计划,即使是简单的查询,如果足够的参数发生变化。   你可能会很幸运,没有改变计划,或者你可能没有   想一想这个问题并添加一个ORDER BY。

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