SQL中TOP和MAX()/MIN()的區別
以我的經驗
SELECT TOP
,比SELECT MIN()
/MAX()
如果您的數據庫中有數千/百萬行如this answer以及我在這裡回答的內容和提問者的回答中看到的要快得多。我的問題是為什麼,在我的理解中,
TOP
查看數據SELECT column FROM table
時,ORDER BY column
它會對結果進行排序,而不是只給你第一行,而MIN()
/MAX()
函式實際上應該只查看每一行檢查總和行,然後轉到下一行,如果該行是>
或<
上一行,則它將結果保存在函式中取決於它是 aMAX()
還是 aMIN()
,這正是ORDER BY
應該做的。請不要回答,根據您的經驗,這
MAX()
要好於問題,因為問題是/和TOP
之間真的有什麼區別?兩者都查看每一行的數據,並且都可能是log(n)。MAX()``MIN()``TOP
回复@JD:
一個簡單的例子是,如果您使用沒有 ORDER BY 子句的 TOP。然後,您將獲得的最高結果可能是不確定的,並且並不總是必須是 MAX() 聚合函式將引用的同一行。
絕對我只是問你什麼時候使用,
ORDER BY
因為它的強大TOP
之處在於以特定方式對其進行排序。關於log(n)我會以不同的方式問它,如果它
ORDER BY
有一個Ω(n)因為它需要查看的最小數據是n並且可能有一個O() >= n因為它可能正在使用最佳排序算法O(n)。有了它,
MIN()
它也可能是Ω(n)和O(n)因為它總是需要掃描所有數據才能找到答案,而且永遠不會超過n,那麼為什麼它有時會產生巨大的差異呢?換一種方式:
如果我有一個包含一百萬行的表,其中包含客戶以及他們購買產品所花費的金額,如果我正在使用
SELECT TOP 1 amount_column FROM customer_table ORDER BY amount_column DESC
並使用SELECT MAX(amount_column) FROM customer_table
第一個需求來查看所有數據amount_column
並對其進行降序排序,那麼執行時間有什麼區別order 所以它是否已經排序並沒有什麼區別,因為它需要檢查所有行是否大於前一行,然後在完成執行時返回最大數量。當我使用該
MAX()
函式執行此操作時,它還需要掃描(在我的理解中)所有行並將第一行保存到結果中,然後轉到下一行並檢查它是否大於結果,如果是,則將其保存到整個表的結果,依此類推,當它完成時,它返回最大數量。因此,在我的理解中,兩者實際上都在做同樣的事情,或者我對它執行功能的方式的理解是錯誤的,這就是我要問的是否我錯了?為什麼?
問題是它們並不總是相同的,因此它們是具有不同目的的不同運營商。其中一些目的重疊,是的,但它們並不完全是一對一的。
一個簡單的例子是如果你
TOP
不使用ORDER BY
子句。然後,您將獲得的最高結果可能是不確定的,並且不一定總是MAX()
聚合函式將引用的同一行。正如mustaccio 在評論中指出的那樣,執行計劃將具體告訴您兩個查詢之間的哪些操作不同,一個是 using
TOP
,另一個是 usingMAX()
。如果沒有特定的查詢,就沒有一個關於兩者如何相似或不同的單一答案,因為它可能因每個特定案例而異。最後,假設兩個運算符的時間大 O 函式始終為O(log(n))也是不正確的,並且取決於數據的結構方式以及應用這些運算符的數據點。在按升序索引的
Table1
列中,查詢可能按O(log(n))的順序(儘管我不確定它是否甚至可能是O(1),因為該子句與索引排序匹配)但是 a可能是**O(n)**的數量級,因為 column 上沒有覆蓋索引,並且可能需要掃描整個表。(A, B, C)``A``SELECT TOP 1 A FROM Table1 ORDER BY A``ORDER BY``SELECT MAX(B) FROM Table1``B
關於您的更新,聚合函式
MIN()
也不MAX()
需要總是掃描所有數據。我的第一個範例只是為了展示 Big O 搜尋時間複雜度在一個特定案例之間MAX()
和TOP
一個特定案例中的差異。但是使用相同的表範例,具有相同的列和索引A
僅覆蓋列升序,那麼查詢SELECT MAX(A) FROM Table1
也應該產生**O(log(n))**的時間複雜度。儘管甚至只關注使用該子句的查詢,但vs和
ORDER BY
之間的異同仍然會因一個案例而異,這直接取決於正在執行的查詢,以及查詢引擎為該查詢生成的執行計劃。如果您有想要討論的特定查詢和執行計劃,請隨時將其添加到您的問題中,我們可以對其進行適當的分析。TOP``MAX()``MIN()
對於您的最新更新,我相信您被絆倒的地方是資料結構的概念。您一直假設在這兩種情況下都需要分析每一行數據,並且僅在未索引的表(堆資料結構)中或查詢沒有覆蓋索引時才如此。因此,在您的範例中,對於兩個運算符,如果沒有覆蓋.
amount_column
但是,如果它上面有一個索引,降序,這將尊重您的語句“ …如果它已經排序”,那麼數據將儲存在B-Tree資料結構中,這將允許您的查詢在索引上查找並顯著減少執行時間降至**O(log(n))**因為它不再需要比較每一行。它需要比較的行子集遠小於整個表本身。是的,在您的具體範例中,理論上兩個查詢都應該看到相同的搜尋時間複雜度,但實際上這又取決於您的數據的結構(在這種情況下是索引)。此外,還有其他因素可能導致兩個單獨的查詢計劃,實際上兩個查詢之間的執行時確實不同,並且只能在比較兩個實際執行計劃時討論其原因。理論上不可能進行討論,因為它可能因多種原因而有所不同,具體取決於執行計劃本身的具體內容。