Sql 在什么时候应该放弃临时表的表变量?

Sql 在什么时候应该放弃临时表的表变量?,sql,sql-server,tsql,Sql,Sql Server,Tsql,是否存在导致表变量效率低下的行计数?我理解两者之间的差异,并且我看到了一些关于何时达到这一点的不同数据,但我很好奇是否有人知道。在内部,表变量可以在tempdb以及临时表中实例化 它们只是在范围和持久性上有所不同 与流行的观点相反,对临时表的操作确实会影响事务日志,尽管它们不受事务控制 要检查它,请运行以下简单查询: DECLARE @mytable TABLE (id INT NOT NULL PRIMARY KEY) ; WITH q(num) AS (

是否存在导致表变量效率低下的行计数?我理解两者之间的差异,并且我看到了一些关于何时达到这一点的不同数据,但我很好奇是否有人知道。

在内部,表变量可以在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
并浏览两个记录集中的最后一个条目

在第一个记录集中,您将看到42个LOP_INSERT_行条目

在另一批中的第二个记录集中,您将看到42个LOP_DELETE_行条目


它们是表变量超出范围且其记录被删除的结果。

当您需要表上的其他索引而不是可以在临时表变量上创建的索引时,或者对于不可能在可用内存中持久化的较大数据集,当表宽每行字节数超过某个阈值时,这是因为每个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 

其他几个没有提到的区别。。。看到我的答案了吗below@Quassnoi,我将不得不等到我到别处去证实这一点,但是,假设你看到的是你所描述的。。。然后我会重申我的声明,我不会收回它,因为日志的目的是允许更改是事务性的,而不能参与事务的更改不是事务性的,无论是否写入日志。。。可以说,如果无法回滚,那么将其写入日志是没有意义的。事实上,有人可能会争辩说,声明改变。。。不影响事务日志。。。正是因为这个原因,它是误导性的。@Charles:事务日志不限于回滚。例如,它支持延迟写入,允许使用顺序磁盘访问来更新表。@Quassnoi,我做了一些进一步的研究。。。这里的问题是您在错误的日志中查找。tembdb的日志不是事务日志。任何和所有事务的事务日志都与用户数据库相关联。tembdb日志不是事务日志,因此不是事务日志。它只是一根木头。如果在用户数据库上运行yr dbcc log命令,应该可以看到temp表的更改,但不应该看到表变量的更改。。。我必须核实一下point@Quassnoi,事实上,即使标量T-Sql变量也存储在tembDb的日志中……表变量也会记录在事务日志中。@Quassnoi,你确定吗?我知道它们不在MSSql的早期版本中。。。这是否发生了变化?@Charles:它们没有回滚并不意味着它们没有存储在事务日志中。@Quassnoi,对不起,是的,它有。。。tempdb不是事务日志。。。事务日志是允许回滚未提交更改的更改的存储。来自msdn表的变量不参与事务或锁定。。。