SQL Server,带截断的临时表和带删除的表变量

Ric*_*ard 7 sql-server-2005 temp-tables

我有一个存储过程,我在其中创建一个临时表,通常包含1到10行.在存储过程中,此表被截断并填充多次.它被截断,因为这比删除更快.当我因使用删除而受到惩罚(截断对表变量不起作用)时,通过用表变量替换此临时表,我是否可以获得任何性能提升

虽然表变量主要在内存中,并且通常比临时表更快,但是我必须通过删除而不是截断来获得任何好处吗?

Adr*_*der 12

对脚本运行followign,似乎表变量是更好的选择

CREATE TABLE #Temp(
        ID INT
)

DECLARE @Int INT,
        @InnerInt INT
SELECT  @Int = 1,
        @InnerInt = 1

WHILE @Int < 50000
BEGIN
    WHILE @InnerInt < 10
    BEGIN
        INSERT INTO #Temp SELECT @InnerInt
        SET @InnerInt = @InnerInt + 1
    END
    SELECT @Int = @Int + 1,
            @InnerInt = 1
    TRUNCATE TABLE #Temp
END

DROP TABLE #TEMP

GO

DECLARE @Temp TABLE(
        ID INT
)

DECLARE @Int INT,
        @InnerInt INT
SELECT  @Int = 1,
        @InnerInt = 1

WHILE @Int < 50000
BEGIN
    WHILE @InnerInt < 10
    BEGIN
        INSERT INTO @Temp SELECT @InnerInt
        SET @InnerInt = @InnerInt + 1
    END
    SELECT @Int = @Int + 1,
            @InnerInt = 1
    DELETE FROM @Temp
END
Run Code Online (Sandbox Code Playgroud)

来自Sql Profiler

CPU     Reads   Writes  Duration
36375     2799937   0       39319

vs

CPU     Reads   Writes  Duration
14750   1700031 2       17376   
Run Code Online (Sandbox Code Playgroud)

  • 更确切地说,"DELETE"是更好的选择.与表变量无关,你可以使用`#temp`表和DELETE进行相同的操作.这是一个非常优秀的例子,因为10行都适合一页.`TRUNCATE`从表中释放最后一页,而'DELETE`则不释放.这些表非常小,因此记录已删除行的开销小于不断释放和重新分配表中单个页面的开销.[对于较大的表格,情况有所不同](http://dba.stackexchange.com/q/27309) (8认同)

mar*_*c_s 8

坦率地说,只有10或20(甚至100)个条目,速度的任何差异都将在亚纳秒范围内.忘记它 - 甚至不要浪费你的大脑时间 - 这不是问题!

一般来说

  • 表变量将保留在内存中一定的大小 - 如果它们超出了这个范围,它们也会被转换到tempdb数据库中的磁盘- 就像临时表一样.另外:如果一个临时表只有少数几个条目,那么它们最像是存储在一个8k页面上,一旦你访问其中一个条目,整个页面(以及整个临时表)就会在SQL Server内存中 - 所以即使在这里,表变量确实没有很多好处......

  • 表变量不支持索引或统计信息,这意味着如果你有多个条目,特别是如果你需要搜索和查询这个"实体",你最好使用临时表

总而言之:我个人比表变量更经常使用临时表,特别是如果我有超过10个条目或类似的东西.能够索引临时表并对其进行统计,与表变量可能具有的任何潜在收益相比,通常可以获得大量时间,性能方面.

  • 谢谢,我同意删除和截断之间的区别可能是微不足道的.这真是一个学术问题,因为在我的程序中交换表变量的临时表会产生大约10%的差异.正如"Spender"所说,我刚试过它. (2认同)