表變量,臨時表

9.2 表變量、臨時表

臨時表分爲局部臨時表和全局臨時表,分別以#以及##爲表名前綴。局部臨時表在會話間不能共享,在會話結束後,臨時表會被刪除;全局臨時表在會話間是可共享的,當建立的會話關閉時,全局臨時表也會被刪除。 session

表變量,發現過許多誤解,覺得表變量是內存表,是存儲在內存中的,其實表變量與臨時表同樣,都是存儲在Tempdb中的,表變量是在SQL Server 2000時加入的,當初是爲了解決臨時表形成重編譯的問題而添加的。作個簡單的測試,以下面的語句代碼清單9-1中所示,能夠獲取當前會話使用Tempdb的空間數量,新建一個會話1,首先執行一次查詢,發現user_objects_alloc_page_count字段對應的值是0。建立一個臨時表,並插入一條數據。如圖9-1中所示,使用了1個數據頁。 測試

SELECT * 優化

FROM sys.dm_db_session_space_usage AS ddssu WITH(NOLOCK) spa

WHERE ddssu.session_id=@@SPID 設計

GO blog

CREATE TABLE #tempSpace1(c1 CHAR(8000)) 索引

GO 內存

INSERT INTO #tempSpace1 (c1) 作用域

VALUES ('a') io

GO

SELECT *

FROM sys.dm_db_session_space_usage AS ddssu WITH(NOLOCK)

WHERE ddssu.session_id=@@SPID

GO

代碼清單9-1 查看臨時表Tempdb使用狀況

圖9-1 查看臨時表Tempdb使用結果

相同的,建立一個具備相同類型字段的表變量,查看會話對錶空間的做用狀況,如圖9-2中所示,也使用了一個數據頁。表變量確實使用了Tempdb做爲存儲。既然二者都是存儲在Tempdb中的,那麼爲什麼還會有兩種類型的數據呢,對比一下圖9-1與圖9-2中所顯示的user_objects_dealloc_page_count字段(該字段表示回收的用戶空間的數據頁個數),會發現,圖9-1中字段的值是0,而圖9-2中的值是1,也就是說,表變量已經被回收了。它們的區別,第一個,就是做用域不一樣。表變量是批處理級的,當批處理結束後,表變量就會被回收,而臨時表是會話級的,只能顯式地刪除,或者會話關閉纔會回收。

SELECT *

FROM sys.dm_db_session_space_usage AS ddssu WITH(NOLOCK)

WHERE ddssu.session_id=@@SPID

GO

DECLARE @tempSpace TABLE(c1 CHAR(8000))

INSERT INTO @tempSpace (c1)

VALUES ('a')

GO

SELECT *

FROM sys.dm_db_session_space_usage AS ddssu WITH(NOLOCK)

WHERE ddssu.session_id=@@SPID

GO

SELECT *

FROM sys.dm_db_session_space_usage AS ddssu WITH(NOLOCK)

WHERE ddssu.session_id=@@SPID

GO

代碼清單9-2 查看錶變量Tempdb使用狀況

圖9-2 查看錶變量Tempdb使用結果

表變量與臨時表,存在着幾個較爲明顯的差別,前面提到了,表變量是爲了處理臨時表形成的執行計劃頻繁從新編譯而引進的新的功能。接下來,研究一下,表變量如何避免重編譯。

9.2.1 統計信息

表變量與臨時最大的差別,同時也須要極爲注意的是表變量是,沒有辦法建立統計信息。因此,如前面章節中所介紹的,查詢優化器在分析執行計劃的時候,對錶變量使用"猜想"的方式來分析。這其中的好處就是,沒有統計信息的更新,就不會形成執行計劃的重編譯的問題。

使用下面的語句(直接點擊XML格式的數據行,能夠打開執行計劃的可視化界面),新建臨時表,並插入200條數據,執行查詢,並查看其執行計劃關於表操做的詳細信息,如圖9-3中所示,在臨時表的預估數據行一行信息中,是200條,它的統計信息是準確的。

CREATE TABLE #tempTable1(c1 CHAR(8000));

DECLARE @cnt INT=0;

WHILE(@cnt<200)

BEGIN

    INSERT INTO #tempTable1 (c1)VALUES('a');

    SET @cnt+=1;

END;

SET STATISTICS XML ON

SELECT *

FROM #tempTable1 AS ts

SET STATISTICS XML OFF

代碼清單9-3 臨時表統計信息

圖9-3 臨時表統計信息

下面的語句,能夠查看錶變量的詳細狀況,如圖9-4中,預估行的數量只有1。對於SQL Server來講,表變量是沒有統計信息的,因此SQL Server只能用"猜想"的方式來預估表變量的數據行,SQL Server會認爲表變量都是小表,執行計劃一般也只會用NESTED LOOP來處理表變量的聯接查詢。所以,在使用表變量的時候,建議只應用在小數據量的查詢中。

DECLARE @tempTable1 TABLE(c1 CHAR(8000));

DECLARE @cnt INT=0;

WHILE(@cnt<200)

BEGIN

    INSERT INTO @tempTable1 (c1)VALUES ('a');

    SET @cnt+=1;

END;

SET STATISTICS XML ON

SELECT * FROM @tempTable1 AS ts;

SET STATISTICS XML OFF

代碼清單9-4 表變量統計信息

圖9-4 表變量統計信息

9.2.2 索引

臨時表的索引與普通物理的索引相同,能夠在建立表的時候指定主鍵和惟一約束,同時也能夠在表建立之後再添加、修改或刪除其餘索引。而表變量只能在定義變量的時候指定主鍵或惟一約束,表變量在聲明之後,便不能再添加或刪除任何索引。

9.2.3 表結構修改

臨時表與普通物理表相同,在建立後,能夠再增減字段,修改字段屬性,增長或刪除約束等。而表變量在聲明後,便不能再作任何關於表結構的修改。這也是爲了重編譯而考慮的,由於在當初(SQL Server早期版本設計中)的設計中,表結構的變動是會引發執行計劃的重編譯的。

相關文章
相關標籤/搜索