2011-02-23 95 views
16

我不太瞭解SQL命令如何對大型結果集進行排序。它是否在內存中完成(即當查詢被執行時)?SQL ORDER BY有多昂貴?

在SQL中使用ORDER BY進行排序的速度會比使用Java這樣的語言(假設使用快速排序的快速內置排序)對包含結果的對象鏈表進行排序要快嗎?

+3

它幾乎總是更快,如果數據庫做的。 – rook 2011-02-23 22:32:57

+0

你會猜到什麼數量級? – 2011-02-23 22:40:12

+0

你可以自己計時。比這裏的任何東西都更權威。 – 2011-02-23 22:53:33

回答

13

對數據庫中的數據進行排序幾乎肯定會更高效。數據庫旨在處理大量數據。中間層不可用的數據庫有多種優化可用。如果您打算在中間層編寫一個超高效的排序例程,該例程利用了您對數據所沒有的信息(數據庫沒有)(例如,將數據集中到一個數十臺中間層機器集羣中,以便排序永遠不會泄漏到磁盤上,利用數據大部分命令選擇一種通常不會特別有效的算法的事實),您可能會超出數據庫的排序速度。但這往往是罕見的。

根據查詢,例如,數據庫優化程序可能會選擇一個查詢計劃,該計劃按順序返回數據,而不執行排序。例如,數據庫知道索引中的數據是已排序的,因此它可以選擇執行索引掃描來按順序返回數據,而不必實現和排序整個結果集。如果它必須實現整個結果,它只需要你正在排序的列和某種行標識符(例如Oracle中的ROWID),而不是排序整行數據,就像天真的中間層實現可能會做的那樣。例如,如果在(col1,col2)上有複合索引,並且您決定在UPPER(col2),LOWER(col1)上進行排序,則數據庫可以從索引讀取col1 & col2值,對行標識符進行排序,以及然後從表中獲取數據。當然,數據庫不必這樣做 - 優化器將考慮對從表或各種索引獲取數據的成本進行排序的成本。數據庫可能會得出結論:最有效的方法是執行表掃描,將整行讀入內存並對其進行分類。它可以得出結論,利用索引可以獲得更多的I/O來獲取數據,但通過減少或消除排序成本來彌補。

+0

你可以擴展關於唯一需要的列和行ID的部分。你的意思是它會獲取某些列,對它們進行排序,然後返回並根據排序順序獲取完整的列?這似乎是非常緩慢的雙從磁盤上讀取每一行 – 2011-02-23 22:34:37

+0

@Joda - 擴大了一點。我並不是想暗示它必須多次提取數據,只是爲了優化(或消除)需要進行排序的數據庫可能具有各種結構。 – 2011-02-23 22:44:48

7

答案是......它取決於。如果可以通過使用數據庫中的索引來完成ORDER BY部分,那麼查詢的執行計劃將使用該索引,並且結果將直接從數據庫以正確的順序返回。如果沒有,那麼數據庫將執行排序,但它可能比您將所有結果讀入內存更好(當然,要比將結果讀入鏈接的列表更好)。

+0

我想我只是不明白中間數據結構通常看起來像數據庫將用來做自己的排序。謹慎地擺脫任何光線? – 2011-02-23 22:38:25

+2

任務,如排序的東西,數據庫是擅長的,所以數據結構的設計使有效率的 - 即保持與每一個記錄插入更新例如,平衡二叉樹。索引不包含整個行,只包含記錄ID,主鍵和DB中的位置。當您詢問排序結果時,它可以按照您詢問的順序快速返回這些位置,然後查找結果集的完整行。 – 2011-02-23 22:45:36

+0

只有在**最小的數據集**中,數據庫和應用程序語言的性能相等。 – 2011-02-23 22:49:43

2

確切的方法取決於您使用的產品,但通常全功能的DBMS具有多種排序算法供您使用。一些在磁盤上工作,隨着時間的推移優化空間,一些在內存中工作,優化速度。如果您對血腥細節感興趣,請查看可用開源代碼的源代碼。

儘管可能存在病理情況,例如某些操作系統的qsort()在某些數據分佈方面存在問題,但通過自行排序或使用其他庫可能會獲得更好的結果。如果您必須嘗試一下,但更喜歡使用DBMS來管理您的數據,因爲這是他們擅長的。

0

除非排序基於索引,如果您使用數據庫排序,則可以保證您將等待整個結果集在數據庫中解析並排序,然後才能看到結果集的單個行。

如果您排序它自己的數據可以增量流(網絡受限的環境更好),也許增量有用的應用減少執行延遲即使分揀操作消耗的總時間相同。

根據部署方案,可能有很大的不同,其中與分類相關的額外費用應當支付。在與中間層一起工作的情況下,它是一次性和可擴展的,而數據層向外擴展則更昂貴。如果它花費相同的CPU,但數據庫CPU在運營成本方面的成本是5倍或10倍,那麼在數據庫之外進行實際操作會更便宜。