Oracle

Oracle的EXIST條件比較子查詢結果的順序是什麼?

  • February 4, 2019

我知道對於較大的子查詢,EXIST 比 IN 效果更好,因為它單獨檢查每個子查詢記錄並在找到比較後停止。

假設我可以以某種方式對子查詢進行排序,以使匹配項更有可能位於頂部。EXIST 實際上會遵循返回子查詢的順序嗎?

我知道這種方法有點像一把雙刃劍,為大型子查詢指定順序會對性能產生負面影響。我想我主要只是好奇。

我會建議,不要試圖超越這樣的優化器。它並不總是根據您編寫查詢的方式執行您的查詢。它可能能夠利用索引或備用連接路徑。EXISTS正如上面的 mathguy 所說,和之間的區別IN比以前要好得多。

我實際上希望如果您ORDER BY在查詢中添加一個子句,它可能會使情況變得更糟,因為可能必須檢索、排序整個結果集,然後對照該EXISTS子句進行檢查。但實際上,沒有執行計劃就無法知道。

只需編寫您的查詢,以便它檢索您需要的數據,對其進行測試,然後僅在需要時對其進行優化。引用 Donald Knuth 的話,“過早的優化是萬惡之源。”

如果您正在考慮簡單地添加ORDER BY到子查詢或類似的查詢中,那麼您將試圖強制 SQL 的基於集合的性質更像是一種命令式語言 - 這樣就存在負面優化。

我不了解 Oracle,但許多解析器會抱怨ORDER BY子查詢中的一個(它不是視窗函式的一部分),當他們讓它通過時,查詢規劃器會簡單地忽略它。

如果它確實聽取了訂購子結果的指令,它將被迫收集所有這些,如果子查詢可以返回大量數據或計算複雜(例如呼叫大量使用者定義的函式),可能需要一些時間。然後它需要執行對於大量結果可能意味著昂貴的磁碟假離線的排序。

如果它找到該值,您實際上將明確禁用它的選項以提前中止該部分工作,因此不必繼續查找。

EXIST 實際上會遵循返回子查詢的順序嗎?

是的。作為一個基於集合的操作,它不對它查看的數據的順序做任何假設,因此除了在找到它時接受它之外沒有任何其他選擇。

假設我可以以某種方式對子查詢進行排序,以使匹配項更有可能位於頂部。

如上所述,有一種或兩種情況可能會增加子查詢以特定順序出現的機會。

如果您使用視窗函式來添加序數值、檢查過去/未來的行等( TSQL 中的ROW_NUMBER(),LAG()​​ ,等LEAD()可能與 Oracle 方言中的相同/相似),那麼查詢計劃可能必須對整個結果集進行排序無論如何要遵守該要求。在這種情況下,您可以反轉邏輯,以便它的排序方向可能允許您的EXISTS檢查儘早完成 - 如果您使用row_number分組計數/區分行,那麼您可能不在乎它們是否是上升或下降。

只有在子查詢已經獲取所有內容並對其進行排序時才有用,並且只有當排序是按EXISTS比較器正在檢查的值(或巧合地傾向於相同順序的值)時,所以它可能非常罕見,以至於在它發生在關鍵查詢中之前不值得考慮。

您還可以通過使用索引提示讓計劃者使用特定的索引而不是自由發揮來哄騙特定的排序。同樣在大多數情況下,您可能會迫使查詢計劃器執行一些會使查詢整體變慢而不是改善問題的事情,因此該選項很少存在並且實際上很有幫助。

我會假設,在您考慮諸如此類的技巧的任何情況下,所討論的查詢都可以從更廣泛的重構/重寫中受益更多。

此外,如果您正在考慮這樣的技巧,因為您正在觸及查詢計劃器的限制(或遇到錯誤),請注意計劃器中的未來改進可能會使您的技巧沒有實際意義,或者更糟的是引入您的“技巧”指令的改進排除它實際上能夠使用。

引用自:https://dba.stackexchange.com/questions/228823