[SQL SERVER]釐清資料表變數真相

資料表變數很多人使用,但很多人卻錯得離譜,下面有關資料表變數四個問題,你能正確回答嗎?

1.資料表變數和暫存資料表最大差異?

2.SQL2005~SQL2012的資料表變數是否可以建立索引?

3.小資料量的資料表變數是否存於記憶體?

4.使用資料表變數是否會影響交易紀錄檔?

很多開發人員或DBA很愛使用資料表變數,我得到答案大部分都說小資料量(小於1000)都存在記憶體,

同session又可重複使用並自動釋放資源且不會影響交易紀錄檔,整體來說,比暫存資料表來的好用太多了,

重點是很多技術blog文章都這樣寫,但....讓我一一來釐清這些網路謠言

 

大部分說資料表變數無法建立索引,這是和暫存資料表最大差異(乾脆說寫法不同..XD),

但應該是資料表變數不存在統計值,暫存資料表有統計值,這才是兩者最大差異。

雖然有人會說無法建立索引應該也算最大差異(SQL2014資料表變數才開始支援建立索引),

但SQL2014以前的版本真的都不能建立索引嗎?

所有的疑問,就讓我使用SQL2008 R2 一一幫大家釐清

目前沒有任何暫存資料表和索引。

我用一個簡單範例,回答所有問題

set statistics io,time on
set nocount on

--確認目前所有temptable和index
select t.name, i.name, i.index_id
from tempdb.sys.tables t
join tempdb.sys.indexes i ON t.object_id = i.object_id

--SQL 2005~20012的資料表變數當然可以建立索引
declare @mytest table
(
id int identity(1,1) not null primary key
,c1 int
,c2 varchar(10)
,unique (c1,id)
,unique (c2,id)
)

--只新增4筆資料,網路技術blog文章都說小於1000筆都會存在記憶體(如果你用in-memory table這當然是真的)
insert into @mytest
values (10,'rico'),(20,'sherry'),(30,'fifi'),(40,'pcdou')

--確認是否存在索引
select t.name, i.name, i.index_id
from tempdb.sys.tables t
join tempdb.sys.indexes i ON t.object_id = i.object_id

--確認是否可以使用索引搜尋
select t1.c1 
from @mytest t1 
where c2='rico' and id>0

--確認是否會寫交易紀錄檔
select Operation, AllocUnitName,[End Time] 
from fn_dblog(NULL, NULL)

我建立資料表變數,我也同時宣告了primary key(預設會建立clustered index)和2個unique nonclustered index,

毫無疑問的SQL2014前的資料表變數當然可以建立索引,第一個結果集真實呈現(PK_xxx和2個UQ_xxx)。

資料表變數我只新增4筆資料,但從第一和第三結果集來看,SQL SERVER幫我建立了暫存資料表,並將交易過程所有資料立即寫入交易紀錄檔,

所以小資料量的資料表變數依然存放在disk,並且會耗用交易紀錄檔案空間(你甚至可以kill sqlserver.exe進一步驗證記憶體)。

 

下面執行計畫更可以確認SQL2014前的版本,資料表變數不只可以建立索引,也可以正常使用索引。

答案:

1.資料表變數和暫存資料表最大差異?  Ans:統計值

2.SQL2005~SQL2012的資料表變數是否可以建立索引? Ans:可以,也可正常使用。

3.小資料量的資料表變數是否存於記憶體? Ans:均存在disk(使用tempdb資源)

4使用資料表變數是否會影響交易紀錄檔? Ans:會耗用交易紀錄檔空間。