2010-09-21 58 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,否則我將以不可預測的順序結束,這將極大地影響我的最終用戶報告。