測試環境與方法
- 資料庫:tempdb
- 工具:
sp_spaceused、sys.dm_db_file_space_usage、sys.dm_io_virtual_file_stats、sys.dm_os_buffer_descriptors
- 測試表變數:
DECLARE @tmp TABLE (list_no INT, id INT) 插入 90 萬行
核心發現
1. 磁碟空間與 IO
- 表變數建立並插入資料期間,tempdb 空間增加 ~9 MB
sys.dm_io_virtual_file_stats 顯示寫入位元組增加 ~8.3 MB,證實發生實際磁碟 IO
- 批次結束後空間自動釋放
2. 記憶體緩衝池
- 資料頁面會被緩存至 Buffer Pool (
sys.dm_os_buffer_descriptors 可見)
- 批次結束後緩存頁面逐漸被驅逐
3. 系統表可見性
tempdb.sys.objects 可查詢到表變數內部物件 (名稱如 #A1B2C3...)
- 僅在當前批次可見
表變數 vs 暫存表 對比
| 特性 | 表變數 @table | 暫存表 #table |
| 作用域 | 批次/程序 | Session |
| 統計資訊 | 無 (優化器假設 1 行) | 有 (自動建立/更新) |
| 重編譯 | 少 | 可能觸發 (DDL/統計變更) |
| 平行執行 | 不支援 | 支援 |
| 索引 | 僅 PRIMARY KEY / UNIQUE (行內定義) | 支援所有索引類型 |
| 交易記錄 | 最小 (僅中繼資料) | 完整記錄 |
| 磁碟 IO | 有 (大量資料時) | 有 |
選型建議
- 小資料量 (< 1 萬行)、簡單邏輯、無需統計資訊 → 表變數
- 大資料量、複雜 JOIN/WHERE、需索引、平行查詢 → 暫存表
#temp
- 存儲過程高併發:表變數減少系統表鎖爭用
- 動態 SQL:暫存表跨批次可見,表變數不可
優化技巧
-- 表變數指定主鑰獲得有序掃描
DECLARE @t TABLE (id INT PRIMARY KEY, val VARCHAR(50));
-- 暫存表建立非叢集索引
CREATE INDEX idx_val ON #t(val);
-- 強制重編譯獲得準確基數估計 (暫存表)
OPTION (RECOMPILE);
copyright ©
萬盛學電腦網 all rights reserved