views:

60

answers:

2

Is there a row count that makes table variable's inefficient or what? I understand the differences between the two and I've seen some different figures on when that point is reached, but I'm curious if anyone knows.

+2  A: 

Internally, table variables can be instantiated in tempdb as well as the temporary tables.

They differ in scope and persistence only.

Contrary to the popular belief, operations to the temp tables do affect the transaction log, despite the fact they are not subject to the transaction control.

To check it, run this simple query:

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

and browse the last entries from both recordsets.

In the first recordset, you will see 42 LOP_INSERT_ROWS entries.

In the second recordset (which is in another batch) you will see 42 LOP_DELETE_ROWS entries.

They are the result of the table variable getting out of scope and its record being deleted.

Quassnoi
Several other differences not mentioned... see my answer below
Charles Bretana
@Quassnoi, I will have to wait till I get elsewhere to confirm this, but, assuming what you are seeing is as you describe it... then I would re-word my statment (I would not retract it, as the point of the log is to allow changes to be transactional, and a change which cannot participate in a transaction is NOT transactional, whether it is written to the log or not... arguably, there is no point to writing it in the log if it cannot be rolled back.) in fact, it could be argued that stating that "changes ... do affect the transaction log ..." is misleading, for that very reason.
Charles Bretana
@Charles: transaction log is not limited to rollbacks. For instance, it supports delayed writes which allow updates to the tables to use sequential disk access.
Quassnoi
@Quassnoi, I have done some furthur research... The issue here is that you are looking in the wrong log. The log for tembdb is not the transaction log. The "Transaction Log" for any and all transactions is associated with the USER database. The tembdb log is not transactional, and is therefore not a "Transaction" log. it is just a log. If you run yr dbcc log command on the user database, you should see the changes for the temp table, but you should not for the table variable... (I have to verify this point)
Charles Bretana
@Quassnoi, in fact, even scalar T-Sql variables are stored in the log for tembDb ...
Charles Bretana
@Charles: changes to temporary tables go to the `tempdb` log as well (since that's where they are stored).
Quassnoi
@Quassnoi, Yes, but the tembdb Log is not a transaction Log... It does not participate imn transactions, it has no checkpoints, it is completely flushed (along w/ tempdb itself) if/when the server is restarted.. It may be a "log" but it is not a transaction log...
Charles Bretana
@Charles: my suggestion is to end this discussion since it leads nowhere.
Quassnoi
as you wish, sir
Charles Bretana
+3  A: 

When you need other indices on the table other than those that can be created on a temp table variable, or, for larger datasets (which are not likely to be persisted in available memory), when the table width (number of bytes per row) exceeds some threshold (This is because the number or rows of data per I/O page shrinks and the performance decreases... or if the changes you plan on making to the dataset need to be part of a multi-statement transaction which may need to be rolled back. (changes to Table variables are not written to the transaction log, changes to temp tables are...)

this code demonstrates that table variables are not stored in Transaction log:

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 
Charles Bretana
Table variables are logged into the transaction log as well.
Quassnoi
@Quassnoi, are u sure? I know they were not in earlier versions of MSSql... Has this changed ?
Charles Bretana
http://jahaines.blogspot.com/2010/01/sql-server-myths-debunked-part-1.html#Link1
Quassnoi
@Charles: the fact that they are not rolled back does not mean they are not stored in the transaction log.
Quassnoi
@Quassnoi, sorry, yes it does... tempdb is not the transaction log... the transaction log is the storgae for changes to allow uncommitted changes to be rolled back.
Charles Bretana
from msdn http://blogs.msdn.com/b/sqlserverstorageengine/archive/2008/03/30/sql-server-table-variable-vs-local-temporary-table.aspx "Table variables do not participate in transactions or locking"...
Charles Bretana
@Charles: are you aware of differences between **transaction log** and **transaction control**? Please see the update to my post.
Quassnoi