【问题标题】:Fastest way to delete all the data in a large table删除大表中所有数据的最快方法
【发布时间】:2010-09-09 00:16:45
【问题描述】:

我不得不从包含大约 500 万行的日志表中删除所有行。我最初的尝试是在查询分析器中发出以下命令:

从客户端日志中删除

花了很长时间。

【问题讨论】:

    标签: sql-server tsql


    【解决方案1】:

    查看truncate table,这样会快很多。

    【讨论】:

    • 关于 TRUNCATE 的说明,如果其中一个列是 IDENTITY 列,则 TRUNCATE 会将该列的 SEED 重置为其初始值(定义表时指定的值)。所以从某种意义上说,这就像从一张全新的桌子开始。我发现它对于在重新填充表之前清理数据很有用
    • 是的,在甲骨文世界我们称之为水印移位,其他的不清楚。
    • @Dillie-O: TRUNCATE 可以回滚,只是它取消分配页面的方式不同 - blog.sqlauthority.com/2010/03/04/…
    • @kristof: 但您可以设置 SEQUENCE 起始值 :) 这样您就可以在完成的地方继续使用您的自动增量值(您需要做的就是在截断之前标记最后一个 ID)跨度>
    【解决方案2】:

    我在 msdn transact-SQL 参考中发现了 TRUNCATE TABLE。对于所有感兴趣的人,这里是备注:

    TRUNCATE TABLE 在功能上与没有 WHERE 子句的 DELETE 语句相同:两者都删除表中的所有行。但是 TRUNCATE TABLE 比 DELETE 更快,并且使用的系统和事务日志资源更少。

    DELETE 语句一次删除一个行,并在事务日志中为每个删除的行记录一个条目。 TRUNCATE TABLE 通过解除分配用于存储表数据的数据页来移除数据,并且只有页解除分配记录在事务日志中。

    TRUNCATE TABLE 删除表中的所有行,但表结构及其列、约束、索引等保留。新行标识使用的计数器被重置为列的种子。如果要保留标识计数器,请改用 DELETE。如果要删除表定义及其数据,请使用 DROP TABLE 语句。

    您不能在由 FOREIGN KEY 约束引用的表上使用 TRUNCATE TABLE;相反,使用没有 WHERE 子句的 DELETE 语句。因为没有记录 TRUNCATE TABLE,所以它不能激活触发器。

    TRUNCATE TABLE 不能用于参与索引视图的表。

    【讨论】:

      【解决方案3】:

      TRUNCATE 以某种方式跳过事务日志是一个普遍的误解。

      这是一种误解,在 MSDN 中有明确提及。

      这里的几个 cmets 都引用了这个神话。让我们一起根除它;)

      【讨论】:

      • 正确。截断是一个“最少记录的操作”,但仍被记录。
      【解决方案4】:

      供参考TRUNCATE TABLE 也适用于 MySQL

      【讨论】:

        【解决方案5】:

        我使用以下方法将表格归零,另外还有一个好处是它给我留下了表格的存档副本。

        CREATE TABLE `new_table` LIKE `table`;
        RENAME TABLE `table` TO `old_table`, `new_table` TO `table`;
        

        【讨论】:

        • 但是你还有old_table中的所有数据吗?我明白为什么这很有用 - 但我们不想要数据......
        【解决方案6】:

        忘记截断和删除。维护您的表定义(以防您想重新创建它)并使用 drop table。

        【讨论】:

        • 这比 TRUNCATE 有什么优势?
        【解决方案7】:

        截断表client_log

        是您最好的选择,截断会杀死表格和索引中的所有内容并重置您拥有的所有种子。

        【讨论】:

        • 这是唯一完整的答案(它完成了完整的命令,而不是对其他站点的引用)
        【解决方案8】:

        truncate table 独立于 SQL 平台。如果您怀疑自己可能曾经更改过数据库提供程序,那么您可能会谨慎使用它。

        【讨论】:

        • 哪些 DBMS 不支持 TRUNCATE TABLE? Oracle、SQL Server、Sybase ASE、MySQL、PostgreSQL、DB2 -- 都支持 TRUNCATE TABLE
        【解决方案9】:

        在 SQL Server 上,您可以使用Truncate Table 命令,该命令比常规删除更快,并且使用的资源更少。它也会将任何身份字段重置回种子值。

        truncate 的缺点是它不能用在被外键引用的表上,也不会触发任何触发器。如果出现任何问题,您将无法回滚数据。

        【讨论】:

          【解决方案10】:

          请注意,TRUNCATE 还会重置所有自动递增键(如果您正在使用这些键)。

          如果您不希望丢失自动递增键,可以通过删除集合来加快删除速度(例如,DELETE FROM table WHERE id > 1 AND id

          【讨论】:

            【解决方案11】:

            是的,好吧,删除 500 万行可能需要很长时间。我能想到的唯一可能更快的方法是删除表并重新创建它。当然,这只有在您想删除表中的所有数据时才有效。

            【讨论】:

              【解决方案12】:

              “删除并重新创建表”的建议可能不是一个好建议,因为这会弄乱你的外键。

              你在使用外键,对吧?

              【讨论】:

                【解决方案13】:

                如果您因为外键和/或触发器而无法使用 TRUNCATE TABLE,您可以考虑:

                • 删除所有索引;
                • 执行通常的 DELETE;
                • 重新创建所有索引。

                这可能会加快 DELETE 速度。

                【讨论】:

                  【解决方案14】:

                  我正在修改我之前的声明:

                  你应该明白,通过使用 TRUNCATE 数据将被清除但 什么都不会记录到 事务日志。写入日志 这就是为什么 DELETE 将永远占用 5 万行。我经常使用 TRUNCATE 在开发过程中,但你应该 小心在生产中使用它 数据库,因为您将无法 回滚您的更改。你应该 立即建立一个完整的数据库 执行 TRUNCATE 后备份 为恢复建立新的基础。

                  上述声明旨在提示您确保您了解两者之间的区别。不幸的是,它写得不好并且发表了不受支持的陈述,因为我实际上没有在两者之间进行任何测试。它基于我从其他人那里听到的陈述。

                  来自MSDN

                  DELETE 语句删除第一行 一次并在 每个已删除行的事务日志。 TRUNCATE TABLE 删除数据 释放数据页用于 存储表的数据,并且只有 页面释放记录在 交易记录。

                  我只想说,两者之间存在根本区别,因为存在区别,所以会有一些应用程序可能不合适。

                  【讨论】:

                  • 如果我不再关心桌子怎么办? DROP TABLE 意味着 DELETE 或 TRUNCATE ?我的意思是:执行 TRUNCATE 和 DROP 更快吗?或者只是一个 DROP ? (使用 MSSQL-2008R4)
                  【解决方案15】:
                  DELETE * FROM table_name;
                  

                  过早的优化可能很危险。优化可能意味着做一些奇怪的事情,但如果它有效,你可能想利用它。

                  SELECT DbVendor_SuperFastDeleteAllFunction(tablename, BOZO_BIT) FROM dummy;
                  

                  我认为速度取决于...

                  • 底层数据库:Oracle、Microsoft、MySQL、PostgreSQL、其他、自定义...

                  • 表格、内容和相关表格:

                  可能有删除规则。是否有删除表中所有内容的现有程序?这可以针对特定的底层数据库引擎进行优化吗?我们有多在乎破坏事物/相关数据?假设其他相关表不依赖于该表,执行 DELETE 可能是“最安全”的方式。是否有其他表和查询相关/依赖于该表中的数据?如果我们不太关心这个表是否存在,那么使用 DROP 可能是一种快速的方法,同样取决于底层数据库。

                  DROP TABLE table_name;
                  

                  要删除多少行?是否有其他可以快速收集的信息来优化删除?例如,我们能否判断该表是否已经为空?我们能分辨出有数百、数千、数百万、数十亿行吗?

                  【讨论】:

                    猜你喜欢
                    • 2010-10-27
                    • 2010-10-17
                    • 1970-01-01
                    • 2010-11-25
                    • 2016-09-06
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2015-06-11
                    相关资源
                    最近更新 更多