代码之家  ›  专栏  ›  技术社区  ›  Jim B

截短与删除的优缺点

  •  60
  • Jim B  · 技术社区  · 15 年前

    有人能简要介绍一下使用以下两种说法的利弊吗?

    TRUNCATE TABLE dbo.MyTable
    

    VS

    DELETE FROM dbo.MyTable
    

    他们似乎都做了同样的事情,当一切都说了和做了;但两者之间一定有区别吗?

    12 回复  |  直到 6 年前
        1
  •  82
  •   Fletch    8 年前

    TRUNCATE 不会生成任何回滚数据,这使得它非常快。它只是释放表使用的数据页。

    但是,如果您在事务中并且希望能够“撤消”此删除,则需要使用 DELETE FROM ,这使您能够回滚。

    编辑: 请注意,上述内容对于SQL Server不正确(但它确实适用于Oracle)。在SQL Server中,如果您在事务内部并且事务尚未提交,则可以回滚截断操作。从SQL Server的角度来看,delete-from和truncate之间的一个关键区别是 this : “DELETE语句一次删除一行,并在事务日志中为每个已删除行记录一个条目。truncate table通过取消分配用于存储表数据的数据页来删除数据,并且只在事务日志中记录页取消分配。”

    换句话说,由于在事务日志中只记录页面释放,因此在截断期间日志记录较少,而在记录每一行的删除操作时,日志记录较少。这就是截短速度极快的原因之一。

    还请注意,从该msdn链接,您不能截断外键约束引用的表、参与索引视图或使用事务复制或合并复制发布的表。

    编辑2: 另一个关键点是,truncate表将把您的标识重置为初始种子,而delete-from将从它停止的位置继续递增。 参考:本·罗宾逊的答案。

        2
  •  46
  •   Coding Flow    11 年前

    其他答案中没有提到的另一个关键点是 TRUNCATE TABLE 重置 你的 初始种子的标识 DELETE FROM 将从停止的位置继续递增。

        3
  •  8
  •   Kyle Hale    12 年前

    从安全性的角度来看,另一个区别是截断需要表上的alter特权,而删除只需要该表上的(drum roll)删除权限。

        4
  •  4
  •   Justin Niessner    15 年前

    TRUNCATE TABLE 不记录事务。这意味着对于大桌子来说它是闪电般的快。缺点是您无法撤消操作。

    DELETE FROM 在事务日志中记录要删除的每一行,这样操作需要一段时间,并且会导致事务日志急剧增长。好处是,如果需要,可以撤消操作。

        5
  •  3
  •   Rahul Modi    7 年前

    SQL Server中删除与截断的大纲

    有关此连接之后的完整文章,请执行以下操作: delete vs truncate in sql server

    截断-语法*/ 截断表表名 /*删除-语法*/ 从表名称中删除 在什么情况下 < /代码>

    enter image description here

    /*Truncate - Syntax*/
    TRUNCATE TABLE table_name
    
    /*Delete - Syntax*/
    DELETE FROM table_name
    WHERE some_condition
    
        6
  •  2
  •   CNkatcher    12 年前

    我相信只有在显式事务中执行操作时,删除和截断才能回滚。否则,必须执行还原以恢复删除的数据

        7
  •  1
  •   nvogel    14 年前

    根本区别在于它们的记录方式。删除和截断的记录方式不同,但可以以完全相同的方式回滚。记录所有更改数据的操作。在SQL Server中,没有非日志操作。

        8
  •  0
  •   yakya    8 年前

    有一件事非常重要(IMO),其他答案中没有提到 TRUNCATE 需要模式稳定锁, Sch-S DELETE 使用行锁。让我们检查以下内容:

    BEGIN TRANSACTION;
    
    BEGIN TRY
        -- Truncate below will take LCK_M_SCH_S lock for TABLE_A
        TRUNCATE TABLE TABLE_A
    
        -- Lets say the query below takes 5 hours to execute
        INSERT INTO
            TABLE_A
        SELECT
            *
        FROM
            GIANT_TABLE (NOLOCK)
    END TRY
    BEGIN CATCH
        IF @@TRANCOUNT > 0
            ROLLBACK TRANSACTION;
        THROW
    END CATCH
    
    IF @@TRANCOUNT > 0
        COMMIT TRANSACTION;
    

    现在假设在这个查询开始的1-2分钟后,我们尝试执行以下操作:

    SELECT COUNT(*) FROM TABLE_A (NOLOCK)
    

    注意我用过 NOLOCK 条款。你认为现在会发生什么?此查询将等待5小时。为什么?因为 诺洛克 子句需要 架构稳定性 锁定 TABLE_A 但那 截断 条款有 架构稳定性 已经开始了。因为我们还没有提交事务,所以即使在那之后锁仍然是打开的 截断 条款。 架构稳定性 锁在桌子上基本上意味着 表A 正在通过添加/删除列等进行更改,或者正在被截断。您甚至无法执行以下操作:

    SELECT object_id('TABLE_A')
    

    这也会持续5个小时。但是,如果你换了那个 截断 具有 DELETE FROM 你会看到没有 架构稳定性 锁定表,上面的查询不会被阻塞。

        9
  •  0
  •   Lukasz Szozda    8 年前

    另一个区别是 DELETE VS TRUNCATE 表损坏时的行为。

    例如:

    DELETE FROM table_name;
    

    将以错误结束:

    消息3314,级别21,状态3,第1行

    撤消数据库“…”中记录的操作时,日志记录ID()处出错。通常,特定故障以前作为错误记录在Windows事件日志服务中。从备份还原数据库或文件,或修复数据库。

    消息0,级别20,状态0,行0

    当前命令发生严重错误。结果,如果有的话,应该丢弃。

    同时 截断 将工作:

    TRUNCATE TABLE table_name;
    -- Command(s) completed successfully.
    
        10
  •  0
  •   Melad Basilius    7 年前

    加上所有的答案,另一个需要考虑的问题是 Truncate 不会触发 delete trigger 在桌子上,但是 delete 语句将触发 删除触发器 每行的表。

        11
  •  -1
  •   Вадим Кравчук    9 年前
    $connection = $this->getEntityManager()->getConnection();
    $connection->exec("Truncate TABLE <tablename>;");
    
        12
  •  -2
  •   ScaleOvenStove    15 年前

    truncate不做任何日志记录,delete做任何日志记录,所以如果您有大量的记录,那么您的trans日志是巨大的。