Sql-Server

SQL Server Join/where 處理順序

  • March 1, 2021

在閱讀了 Slow SQL query, not sure how to optimize之後,我開始思考查詢的一般性能。當然,我們需要第一個表的結果(當其他表被連接時)在連接之前盡可能小(這個問題的內連接),以使我們的查詢更快一點。

例如,應該這樣:

SELECT *
FROM   ( SELECT * FROM table1 WHERE col = @val ) t
INNER JOIN table2 ON col = col2

比以下更好/更快:

SELECT *
FROM table1
INNER JOIN table2 ON col = col2
WHERE table1.col = @val

我的理論如下(這可能不是正確的實現,我試圖從我讀過的 SQL Server 2008 內部書籍(MSFT Press)中記住):

  1. 查詢處理器首先獲取左表(table1)
  2. 加入第二個表 (table2) 並在過濾出必要的行之前形成笛卡爾積(如果適用)
  3. 然後使用 SEELCT 語句最後執行 WHERE、ORDER BY、GROUP BY、HAVING 子句。

因此,如果在上面的語句#1 中,表更小,則 SQL 引擎在形成笛卡爾積時要做的工作更少。然後,當您到達 where 語句時,您將在記憶體中篩選出一個縮減的結果集。

我可能離題太遠了,這是不真實的。就像我說的,這是一個理論。

你的意見?

注意:我只是想到了這個問題,還沒有機會自己進行任何測試。

注2:標記為SQL Server,因為我對MySql等的實現一無所知。請隨時回答/評論

查詢的邏輯處理在MSDN上(由 Microsoft SQL Server 團隊編寫,而不是第 3 方)

1. FROM
2. ON
3. JOIN
4. WHERE
5. GROUP BY
6. WITH CUBE or WITH ROLLUP
7. HAVING
8. SELECT
9. DISTINCT
10. ORDER BY
11. TOP

派生表緊隨其後,然後外部查詢再次執行等等

這是合乎邏輯的:不是實際的。不管 SQL Server 實際是如何做的,這些語義都是不折不扣的。“實際”由查詢優化器(QO)確定,您避免使用您提到的中間 Cartesion 產品。

值得一提的是,SQL 是聲明性的:您說“什麼”而不是“如何”,就像您對過程/命令式程式(Java、.net)所說的那樣。因此,在許多情況下說“這發生在此之前”是錯誤的(例如假設短路或從左到右的 WHERE 順序)

在上述情況下,無論 QO 的結構如何,它都會生成相同的計劃,因為它是一個簡單的查詢。

但是,QO 是基於成本的,對於復雜的查詢,可能需要 2 週才能生成理想的計劃。所以它確實“足夠好”,但實際上並非如此。

因此,您的第一個案例可能會幫助優化器找到更好的計劃,因為 2 個查詢的邏輯處理順序不同。但它可能不會。

我在 SQL Server 2000 上使用了這個技巧,使報告查詢的速度提高了 60 倍。隨著 QO 不斷改進版本,它會更好地解決這些問題。

而你提到的書:有一些爭議

參見SO和後續連結:https ://stackoverflow.com/q/3270338/27535

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