基本子查詢評估
我是子查詢的新手。是否有關於如何評估和執行基本子查詢的一般策略(除了 sql 引擎自動優化它們)。例如,考慮這個選擇查詢:
select * from "users" order by "users"."id" asc limit 1000 offset 0;
如果我們這樣轉換執行計劃會怎樣?
select * (select * from users) as u order by u.id asc limit 1000 offset 0;
更具體地說,在第二個範例中,sql 引擎是否會在限制所有行之前先獲取所有行(並使其變慢)?
我正在使用 postgres 13.3,這很重要。
讓我們以應用程序開發為例。在那裡,功能規範描述了系統的行為。它詳細說明了輸出應該是什麼、如何格式化以及如何排序。只要滿足指定的條件,程序員就可以自由地以任何方式實現這些要求。功能規範沒有關於變數名、記憶體結構或任何實現細節的內容。
在 DBMS 中,“功能規範”是 SQL。它描述了輸出的內容和格式,但沒有說明應該讀取哪些資料結構或文件、如何讀取或以什麼順序讀取。這些實現選擇由查詢優化器 (QO) 做出。它在這個類比中扮演應用程序程序員的角色。
所以我很遺憾地說“除了 sql 引擎自動優化它們之外”沒有太多其他東西。優化器可以自由地將送出的 SQL 重新排列為任何保證返回相同結果的替代方案。在您給定的範例中,它發現子查詢與直接引用表相同。這就是執行計劃相同的原因 - 因為這兩個查詢意味著相同的事情,保證在所有情況下都返回相同的結果,並且 QO 已經確定了這一點。
所以不,內部查詢不會被評估然後被過濾。它從執行時執行計劃中消除。
複雜的子查詢(例如,在 SELECT 列表中,或與外部查詢相關)需要更多考慮. 在處理這些問題時,QO 並不總是有好的選擇。根據送出的 SQL,性能可能會有很大差異。
使用 PostgreSQL 的內置函式
EXPLAIN (ANALYZE,BUFFERS) select ...
來查看兩個查詢的執行計劃。在您的特定非常簡單的範例中,PostgreSQL 幾乎肯定會生成一個相同的計劃。正如我上面所說,查詢越複雜,您就越有可能看到變化。