2010-05-27 54 views

回答

3

如果表中除了那些可以在臨時表變量上創建的索引,或者對於較大的數據集(不可能保留在可用內存中),表格寬度(數目每行的字節數)超過某個閾值(這是因爲每個I/O頁面的數據或行數減少並且性能下降......或者如果計劃對數據集進行的更改需要成爲多語句的一部分(對錶變量的更改不寫入事務日誌,對臨時表的更改爲...)

此代碼演示表變量未存儲在事務日誌中:

create table #T (s varchar(128)) 
declare @T table (s varchar(128)) 
insert into #T select 'old value #' 
insert into @T select 'old value @' 
begin transaction 
    update #T set s='new value #' 
    update @T set s='new value @' 
rollback transaction 
select * from #T 
select * from @T 
+1

表變量也會記錄到事務日誌中。 – Quassnoi 2010-05-27 13:49:46

+0

@Quassnoi,你確定嗎?我知道他們不在早期版本的MSSql中......這有改變嗎? – 2010-05-27 13:54:34

+0

http://jahaines.blogspot.com/2010/01/sql-server-myths-debunked-part-1.html#Link1 – Quassnoi 2010-05-27 13:58:22

2

在內部,表變量可以在tempdb以及臨時表中實例化。

它們僅在範圍和持久性方面有所不同。

與流行的觀點相反,對臨時表的操作確實會影響事務日誌,儘管事實上它們不受事務控制的限制。

要檢查它,運行這個簡單的查詢:

DECLARE @mytable TABLE (id INT NOT NULL PRIMARY KEY) 
; 
WITH q(num) AS 
     (
     SELECT 1 
     UNION ALL 
     SELECT num + 1 
     FROM q 
     WHERE num <= 42 
     ) 
INSERT 
INTO @mytable (id) 
SELECT num 
FROM q 
OPTION (MAXRECURSION 0) 

DBCC LOG(tempdb, -1) 
GO 
DBCC LOG(tempdb, -1) 
GO 

,並從兩個瀏覽記錄集的最後一個條目。

在第一個記錄集中,您將看到42LOP_INSERT_ROWS條目。

在第二個記錄集(這是另一批次)中,您將看到42LOP_DELETE_ROWS條目。

它們是表變量超出範圍並且其記錄被刪除的結果。

+0

還有幾個其他的區別沒有提到......看到我的回答如下 – 2010-05-27 13:47:25

+0

@Quassnoi,我將不得不等待,直到我到別處去證實這一點,但是,假設你所看到的是你描述的那樣...然後我會重新聲明我的陳述(我不會收回它,因爲日誌的目的是允許更改是事務性的,並且不能參與事務的更改不是事務性的,無論它是否寫入日誌。 ..可以說,如果它不能被回滾,就沒有必要在日誌中寫入它)。事實上,可以說,「改變......確實會影響事務日誌......」是有誤導性的,因爲就是這個原因。 – 2010-05-27 14:51:45

+0

@Charles:事務日誌不限於回滾。例如,它支持延遲寫入,允許對錶進行更新以使用順序磁盤訪問。 – Quassnoi 2010-05-27 15:00:21

相關問題