【问题标题】:SQL Server, temporary tables with truncate vs table variable with deleteSQL Server,带有截断的临时表与带有删除的表变量
【发布时间】:2011-02-08 10:55:52
【问题描述】:

我有一个存储过程,我在其中创建了一个临时表,该表通常包含 1 到 10 行。该表在存储过程中被截断并填充了很多次。它被截断,因为这比删除更快。 当我因使用删除而受到惩罚时(截断不适用于表变量),是否可以通过用表变量替换此临时表来提高性能?

虽然表变量主要在内存中并且通常比临时表快,但我是否会因为必须删除而不是截断而失去任何好处?

【问题讨论】:

    标签: sql-server-2005 temp-tables


    【解决方案1】:

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

    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
    

    来自 Sql Profiler

    CPU     Reads   Writes  Duration
    36375     2799937   0       39319
    
    vs
    
    CPU     Reads   Writes  Duration
    14750   1700031 2       17376   
    

    【讨论】:

    • 更准确的说法是DELETE 是更好的选择。与#temp 表和DELETE 相同的表变量无关。这是一个非常极端的情况,因为 10 行都适合一页。 TRUNCATE 释放表中的最后一页,DELETE 没有。这些表非常小,因此记录已删除行的开销小于不断释放和重新分配表中单个页面的开销。 For larger tables the story is different
    • 所以.... truncate 对于一个更大的表会更好,比如 1000 行?对于清除数据,截断通常比删除快得多,因为它会不加选择地清除所有数据,并且不会像删除单个行那样向日志写入几乎那么多。
    【解决方案2】:

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

    一般

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

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

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

    【讨论】:

    • 谢谢,我同意删除和截断之间的区别可能可以忽略不计。这确实是一个学术问题,因为在我的程序中将临时表换成表变量会产生大约 10% 的差异。正如“Spender”所说,我刚刚测试了它。
    • 我想知道自己与 OP 的情况相似。临时表可以是 10、25、250 行,具体取决于数据的设置方式。在我的测试场景 15 行中,我正在比较一个 proc 中的实际执行计划,该 proc 有一个迭代的临时表,然后在外循环中再次重用。我们不想有过时的数据,所以我们用 DELETE 清除临时表。这显示在执行计划中,占批次的 4%(其复杂的批次正在进行)。如果我用 TRUNCATE 替换它根本不在计划中!这是 truncate 的正常行为(不会出现在执行计划中)还是与计划无关?
    猜你喜欢
    • 1970-01-01
    • 2013-04-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-22
    • 1970-01-01
    相关资源
    最近更新 更多