SQL Server Join/where 處理順序
在閱讀了 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)中記住):
- 查詢處理器首先獲取左表(table1)
- 加入第二個表 (table2) 並在過濾出必要的行之前形成笛卡爾積(如果適用)
- 然後使用 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 不斷改進版本,它會更好地解決這些問題。
而你提到的書:有一些爭議