2010-09-21 23 views
8

也许有人可以向我解释这一点,但是当从Oracle查询数据表(其中存在多个记录(例如客户ID))时,对于该客户而言首先出现的记录可以变化,如果没有隐含的“order by”语句通过例如交易类型等替代字段来强制执行订单。因此,在同一张表上运行相同的查询可能会产生与10分钟前不同的记录排序。当没有使用“order by”子句时,Oracle SQL以任意方式返回行

例如,一次运行可以产生:

CUST_ID,TRANSACTION_TYPE
123甲
123乙

除非 “由TRANSACTION_TYPE顺序” 子句中使用的,甲骨文可以任意地返回以下结果的下一个时间运行查询:

CUST_ID,TRANSACTION_TYPE
123乙
123甲

我想我的印象是在Oracle中有一个数据库默认的行排序(可能)反映了磁盘介质上的物理顺序。换句话说,一个任意的顺序是不变的,并且在查询重新运行时可以保证得到相同的结果。

这是否与优化器有关,以及它如何决定最有效地检索数据的位置?

当然,从编程的角度来看,最好的做法是强制任何需要的顺序,我只是有点不安这种行为。

+0

我不知道为什么,但这是一个非常有趣的观察,尤其是它的'不安'部分。 :) – 2010-09-21 21:12:56

+0

你不*强迫*订购,你*选择*它。 – egrunin 2010-09-22 13:37:56

回答

8

有没有默认的排序,永远。如果你没有指定ORDER BY,你可以得到相同的结果第10000次,那么它可以改变。

请注意,即使ORDER BY的值相同,也是如此。例如:

Col1 Col2 
1 1 
2 1 
3 2 
4 2 

如果使用ORDER BY Col2,你还是不知道的行1或2将是第一位的。

22

SELECT声明中返回给应用程序的行的顺序是完全是任意的,除非另有说明。如果您希望,需要或期望行按特定顺序返回,则用户有责任指定此类订单。 (注意:如果使用某些操作,Oracle的某些版本会按升序隐式排序数据,例如DISTINCT, UNION, MINUS, INTERSECTGROUP BY。但是,由于Oracle实施了散列排序,因此数据类型的性质可能会有所不同,并且依赖于该功能的许多SQL都打破了。)

+6

+1(或者更准确地说,依赖于该特性的大量SQL被暴露为一直被破坏*) – 2010-09-22 04:26:35

+1

我几乎希望ORGANIZATION子句是必需的,所以人们会意识到,默认情况下,在Oracle中,表是堆 - 举办。 – 2010-09-22 14:19:24

+1

+1 - 但这需要使用Oracle多年的人(包括自己在内)必须了解CREATE TABLE的ORGANIZATION子句意味着什么(并感谢您的意见,促使我对此进行了阅读)。 – 2010-09-22 16:32:58

5

简单的答案是,SQL标准说没有默认的没有ORDER BY语句的查询顺序,所以你不应该假设它。

真正的原因可能与分配给每行的哈希值在被拉入记录集时有关。没有理由假设一致的哈希。

6

只需将图像中的行像篮子中的球一样成像即可。球有订单吗?

我不认为有任何数据库管理系统保证订单如果没有指定ORDER BY。

一些可能总是按照它们插入的顺序返回行,但这是一种实现副作用。

某些执行计划可能导致结果集即使没有ORDER BY也会被排序,但这又是一个您不应该依赖的实现副作用。

6

如果ORDER BY子句不存在,那么数据库(不仅仅是Oracle - 任何关系数据库)可以按照发生它们的顺序自由返回行。这将取决于优化器选择的查询计划。

如果返回行的顺序很重要,则必须使用ORDER BY子句。你有时可能会很幸运,并且行会按照你希望他们甚至没有ORDER BY的顺序返回,但是不能保证A)你会在其他查询中幸运的,以及B)这些行的顺序明天将返回与今天返回的顺序相同。

此外,数据库产品的更新可能会改变查询的行为。去年进行重大版本升级时,当我们发现Oracle 10以不同于Oracle 9的顺序返回GROUP BY结果时,我们不得不争论一点。原因 - 没有ORDER BY子句。

ORDER BY - 当返回的数据的顺序真的很重要。

+0

哇,群并不会自动暗示顺序。谢谢,我必须记住这一点。这是SAS SQL(称为proc sql)与Oracle SQL不同的另一个实例。当一个group by子句出现时,Proc SQL实际上会忽略一个多余的顺序。 – jgunnink 2010-09-22 20:17:28

2

如果您不使用ORDER BY,则订单为任意;然而,依赖于物理存储和内存方面。 因此,如果您在10分钟内重复相同的查询数百次,则每次都会得到几乎相同的顺序,因为可能没有任何更改。

事情会改变“NOORDER令”是:

  • 执行计划 - 如果改变(你已经指出 是)
  • 插入和删除在查询中涉及的表。
  • 其他的东西像行的内存存在。(其它表上的其他querys可能影响的是)
+0

你说得对,大部分情况都不会改变。我刚刚注意到,在返回一百万行的查询中,几千个连续运行之间可能会有所不同。我在Oracle方面更加专业的同事向我解释说,即使引用的代码运行和表格是静态的,结果也可能基于一些运行时间因素,其中一些因素是您提到的。它实际上让我对Oracle在幕后做多少事情有了新的认识,以最大限度地提高检索速度。 – jgunnink 2010-09-23 15:42:31

0

当你进入并行数据检索I/O是不是有可能得到不同的不同序列运行,即使没有更改存储的数据?

也就是说,在多处理环境中,并行线程完成的顺序是未定义的,并且可能随同一共享处理器上发生的其他情况而变化。

+0

我不认为有什么建议在这里涉及到并行数据检索。 – 2013-05-31 17:32:01

0

由于我是Oracle数据库引擎的新手,我注意到我的SELECT语句中没有ORDER BY这一行为。

我一直在使用Microsoft SQL Server多年。 SQL Server引擎总是会检索由表的“集群索引”(基本上是主键索引)排序的数据。 SQL Server将始终以基于聚簇索引的连续顺序插入新数据。

因此,当您在没有SQL Server顺序的表上执行选择时,它将始终检索按主键值排序的数据。

ORDER BY可能会导致严重的性能开销,这就是为什么你不想使用它,除非你不满意不一致的结果顺序。

我得出的结论是,在我所有的Oracle查询中,我必须使用ORDER BY,否则我将以不可预测的顺序结束,这将极大地影响我的最终用户报告。