无序导致SQL

时间:2014-01-27 00:24:58

标签: sql sql-server oracle tsql

我一遍又一遍地读到它,SQL的核心是无序模型。这意味着多次执行相同的SQL查询可以以不同的顺序返回结果集,除非包含“order by”子句。有人可以解释为什么SQL查询可以在运行查询的不同实例中以不同的顺序返回结果集吗?它可能并非总是如此,但它当然是可能的。

从算法上讲,当没有“order by”子句时,查询计划在确定结果集的顺序时不起任何作用吗?我的意思是当有一些查询的查询计划时,算法如何不总是以相同的顺序返回数据?

注意:我没有质疑订单的使用,我问为什么没有保证,因为我正在试图理解由于无法保证所带来的挑战。

5 个答案:

答案 0 :(得分:16)

完全相同的执行计划可以返回不同排序结果的一些SQL Server示例

  1. 无序索引扫描可能以allocation order或密钥顺序执行,具体取决于有效的隔离级别。
  2. merry go round scanning功能允许在并发查询之间共享扫描。
  3. 并行计划通常是非确定性的,结果的顺序可能取决于运行时选择的并行度和服务器上的并发工作负载。
  4. 如果该计划嵌套了带有无序预取的循环allows the inner side of the join to proceed using data from whichever I/Os happened to complete first

答案 1 :(得分:7)

马丁史密斯有一些很好的例子,但是证明SQL Server何时会改变所使用的计划的绝对死的简单方法(因此根据不同的计划,将使用不使用ORDER BY的查询的顺序)是添加覆盖指数。举个简单的例子:

CREATE TABLE dbo.floob
(
  blat INT PRIMARY KEY, 
  x VARCHAR(32)
);

INSERT dbo.floob VALUES(1,'zzz'),(2,'aaa'),(3,'mmm');

这将按群集PK命令:

SELECT x FROM dbo.floob;

结果:

x
----
zzz
aaa
mmm

现在,让我们添加一个恰好涵盖上述查询的索引。

CREATE INDEX x ON dbo.floob(x);

当我们再次运行它时,索引会重新编译上面的查询;现在它按新索引排序,因为该索引为SQL Server提供了一种更有效的方式来返回结果以满足查询:

SELECT x FROM dbo.floob;

结果:

x
----
aaa
mmm
zzz

看看计划 - 既没有排序运算符,也只是 - 没有任何其他排序输入 - 依赖于索引的固有顺序,他们正在扫描整个索引,因为它们必须(和最便宜的) SQL Server扫描索引的方式是按顺序)。 (当然,即使在这些简单的情况下,马丁答案中的一些因素也会影响不同的顺序;但在没有任何这些因素的情况下也是如此。)

正如其他人所说, 仅依赖于订单的方式 指定订购 。请把它写在某个地方。无论有多少场景存在,这种信念可能会破裂;甚至有一个这样的事实使得试图找到一些指导方针,因为你可以懒惰而不使用ORDER BY子句是徒劳的。只需始终使用它,或者为数据做好准备,并不总是以相同的顺序返回。

有关此问题的一些相关想法:

答案 2 :(得分:2)

来自维基百科的引用:

“由于SQL是一种声明性编程语言,SELECT查询指定了一个结果集,但没有指定如何计算它。数据库将查询转换为”查询计划“,这可能因执行而异,数据库版本和数据库软件。此功能称为“查询优化器”,因为它负责在适用的约束内为查询找到最佳的执行计划。“

这完全取决于查询优化器选择什么作为计划 - 表扫描,索引扫描,索引搜索等。

可能影响选择计划的其他因素包括表/索引统计和参数嗅探,仅举几例。

简而言之,如果没有ORDER BY子句,订单永远无法保证。

答案 3 :(得分:2)

这很简单:如果您需要订购数据,请使用ORDER BY。这不难!

它可能不会在今天或下周甚至下个月引起您的问题,但有一天会发生问题。

我一直在进行一个项目,我们需要在升级到Oracle 10g之后重写几十(或几百)个查询,导致GROUP BY以与Oracle 9i不同的方式进行评估,这意味着查询不一定按分组列排序。没有乐趣,也很容易避免。

请记住,SQL是声明性语言,因此您告诉DBMS您想要什么,然后DBMS会研究如何获取它。它每次都会带来相同的结果,但每次都可能以不同的方式进行评估:没有任何保证。

这可能会导致问题的一个简单示例是,如果从表中选择,则会在表的末尾显示新行,直到它们没有,因为您删除了一些行和DBMS决定填补空白区域。

除非您使用ORDER BY,否则有多种方法可能会出错。

为什么水在100摄氏度下沸腾?因为这是它的定义方式。

为什么没有ORDER BY就没有关于结果排序的保证?因为这是它的定义方式。

DBMS下次可能会使用相同的查询计划,而查询计划可能会以相同的顺序返回数据:但这不是保证,甚至不接近保证。

答案 4 :(得分:0)

如果您没有指定ORDER BY,那么订单将取决于它使用的计划,例如,如果查询执行了表扫描并且没有使用索引,那么结果将是“自然顺序”或顺序PK。但是,如果计划确定使用基于columnA的IndexA,则订单将按此顺序排列。有意义吗?