估計基數時,優化器如何處理尚未填充的#temp 表?
我一直在建構儲存過程,但找不到任何關於 SQL Server 優化器如何處理 #temp 表的文件。
如果我在儲存過程執行期間創建了 #temp 表的 #temp 表有 4 個連接,並且 #temp 表可能包含零到多條記錄,它是如何估計的?
由於CREATE/ALTER時沒有統計資訊,估計和join中的一些表一樣大嗎?估計很小嗎?估計和其他#temporary表一樣嗎?
請注意,這是假設在執行時沒有重新編譯並且使用原始版本。
SQL Server 通常會在儲存過程開始執行之前為儲存過程中的語句建構一套完整的執行計劃。
當存在臨時表時,該方法會稍作修改:
- 引用臨時表的每個語句的編譯都會延遲到該語句實際執行。
- 自 2005 版本以來,SQL Server 就支持**語句級重新編譯。**只有受影響的語句被重新編譯;該程序的其餘計劃不受影響。
- 延遲編譯意味著 SQL Server 在優化期間知道臨時表的執行時基數。
- SQL Server 還可以自動創建統計資訊以支持正在編譯的查詢。這發生在編譯期間,從技術上講會導致重新編譯。
- 因此,建構的執行計劃受益於準確的基數資訊和自動創建的統計對象(如果啟用了該選項)。
從有關重新編譯執行計劃的文件中:
在 2005 之前的 SQL Server 版本中,每當批處理中的語句導致重新編譯時,整個批處理(無論是通過儲存過程、觸發器、臨時批處理還是預準備語句送出)都會重新編譯。從 SQL Server 2005 (9.x) 開始,僅重新編譯批處理中觸發重新編譯的語句。此外,由於 SQL Server 2005 (9.x) 及更高版本具有擴展的功能集,因此還有其他類型的重新編譯。
語句級重新編譯有利於性能,因為在大多數情況下,少量語句會導致重新編譯及其相關的損失,就 CPU 時間和鎖而言。因此,對於批處理中不必重新編譯的其他語句,可以避免這些懲罰。
並來自表變數延遲編譯:
使用表變數延遲編譯,引用表變數的語句的編譯將延遲到該語句的第一次實際執行。這種延遲編譯行為與臨時表的行為相同。
這是基本的大綱,但不是全部。
正如在另一個答案中已經指出的那樣,儲存過程中的臨時表也可以被記憶體以供重用。這種記憶體可以顯著提高性能和可伸縮性,但它確實使計劃重新編譯的條件和統計資訊的維護方式變得複雜。
我在Temporary Table Caching Explained和Temporary Table Caching in Stored Procedures 中為感興趣的(和高級的)讀者描述了這些額外的複雜性。