解答 1:與臨時表相比,表變量具有下列優點:
• | 如 SQL Server 聯機叢書“表”(Table) 一文中所述,表變量(如局部變量)具有明確定義的範圍,在該範圍結束時會自動清除這些表變量。 |
• | 與臨時表相比,表變量導致存儲過程的重新編譯更少。 |
• | 涉及表變量的事務僅維持表變量上更新的持續時間。因此,使用表變量時,需要鎖定和記錄資源的情況更少。因爲表變量具有有限的範圍並且不是持久性數據庫的一部分,所以事務回滾並不影響它們。 |
解答 2:下面的文章討論了重新編譯存儲過程的一些原因:
表變量完全獨立於創建這些表變量的批,因此,當執行 CREATE 或 ALTER 語句時,不會發生“重新解析”,而在使用臨時表時可能會發生“重新解析”。臨時表需要此“重新解析”,以便從嵌套存儲過程引用該表。表變量完全避免了此問題,因此存儲過程可以使用已編譯的計劃,從而節省了處理存儲過程的資源。
問題 3:表變量有哪些缺陷?
解答 3:與臨時表相比,它存在下列缺陷:
• | 在表變量上不能創建非聚集索引(爲 PRIMARY 或 UNIQUE 約束創建的系統索引除外)。與具有非聚集索引的臨時表相比,這可能會影響查詢性能。 |
• | 表變量不像臨時表那樣可以維護統計信息。在表變量上,不能通過自動創建或使用 CREATE STATISTICS 語句來創建統計信息。因此,在大表上進行復雜查詢時,缺少統計信息可能會妨礙優化器確定查詢的最佳計劃,從而影響該查詢的性能。 |
• | 在初始 DECLARE 語句後不能更改表定義。 |
• | 表變量不能在 INSERT EXEC 或 SELECT INTO 語句中使用。 |
• | 表類型聲明中的檢查約束、默認值以及計算所得的列不能調用用戶定義的函數。 |
• | 如果表變量是在 EXEC 語句或 sp_executesql 存儲過程外創建的,則不能使用 EXEC 語句或 sp_executesql 存儲過程來運行引用該表變量的動態 SQL Server 查詢。由於表變量只能在它們的本地作用域中引用,因此 EXEC 語句和 sp_executesql 存儲過程將在表變量的作用域之外。但是,您可以在 EXEC 語句或 sp_executesql 存儲過程內創建表變量並執行所有處理,因爲這樣表變量本地作用域將位於 EXEC 語句或 sp_executesql 存儲過程中。 |
解答 4:表變量不是僅存在於內存中的結構。由於表變量可能保留的數據較多,內存中容納不下,因此它必須在磁盤上有一個位置來存儲數據。與臨時表類似,表變量是在 tempdb 數據庫中創建的。如果有足夠的內存,則表變量和臨時表都在內存(數據緩存)中創建和處理。
問題 5:必須使用表變量來代替臨時表嗎?
解答 5:答案取決於以下三個因素:
• | 插入到表中的行數。 |
• | 從中保存查詢的重新編譯的次數。 |
• | 查詢類型及其對性能的指數和統計信息的依賴性。 |
通常情況下,應儘量使用表變量,除非數據量非常大並且需要重複使用表。在這種情況下,可以在臨時表上創建索引以提高查詢性能。但是,各種方案可能互不相同。Microsoft 建議您做一個測試,來驗證表變量對於特定的查詢或存儲過程是否比臨時表更有效。