【问题标题】:what is the best way to delete millions of records in TSQL?在 SQL 中删除数百万条记录的最佳方法是什么?
【发布时间】:2014-05-14 18:19:52
【问题描述】:

我有一个下表结构

Table1       Table2        Table3
--------------------------------
 sId          sId           sId
 name          x              y
  x1          x2             x3

我想根据 sId 从 table1 中删除所有在 table3 中没有匹配记录的记录,如果 table2 中存在 sId,则不要从 table1 中删除记录。table1 中大约有 20,15 和 10 百万条记录,table2 & table3 分别 --我做过这样的事情

Delete Top (3000000)
        From Table1 A
        Left Join Table2 B
        on A.Name ='XYZ' and
           B.sId = A.sId
        Left Join Table3 C
        on A.Name = 'XYZ' and
           C.sId = A.sId

((我在 sId 上添加了索引,但在 Name 上没有。)) 但这需要很长时间才能删除记录。 有没有更好的方法来删除数百万条记录? 提前致谢。

【问题讨论】:

标签: sql sql-server tsql


【解决方案1】:

如果您需要删除少于 40% 的数据,则分批执行 5000 或 10000你又在另一张桌子上倾倒了/bcp in

while @@rowcount > 0
begin
Delete Top (5000)
        From Table1 A
        Left Join Table2 B
        on A.Name ='XYZ' and
           B.sId = A.sId
        Left Join Table3 C
        on A.Name = 'XYZ' and
           C.sId = A.sId
end

你可以运行一个小例子来看看会发生什么

CREATE TABLE #test(id INT)

INSERT #test VALUES(1)
INSERT #test VALUES(1)
INSERT #test VALUES(1)
INSERT #test VALUES(1)
INSERT #test VALUES(1)
INSERT #test VALUES(1)
INSERT #test VALUES(1)

WHILE @@rowcount > 0
BEGIN 
DELETE TOP (2) FROM #test

END 

【讨论】:

    【解决方案2】:

    删除数百万条记录的一种方法是选择新表中的剩余记录,然后删除旧表并重命名新表。您可以根据外键选择最适合您的方式,您可以删除并重新创建外键,或者截断旧表中的数据并将所选数据复制回来。

    如果您只需要删除几条记录,请忽略此答案。这是如果您确实想要删除数百万条记录。

    【讨论】:

    • 希望我打字更快。你打败了我。
    【解决方案3】:

    另一种方法是将要保留的数据插入到另一个表中,例如 Table1_good。 完成并验证后: 删除 Table1,然后将 Table1_good 重命名为 Table1

    做这件事的方式很肮脏,但它确实有效。

    【讨论】:

      【解决方案4】:

      使用 top 子句更多是为了提高并发性,实际上可能会使代码运行得更慢。

      一个建议是从派生表中删除数据: http://sqlblogcasts.com/blogs/simons/archive/2009/05/22/DELETE-TOP-x-rows-avoiding-a-table-scan.aspx

      【讨论】:

        【解决方案5】:

        您是否在相关表字段上设置了适当的索引?如果不是,删除记录可能需要很长时间。

        【讨论】:

          【解决方案6】:

          您正在执行的 DELETE 操作正在运行基础 SELECT 语句以查找将被删除的记录。您所做的操作基本上是一个简单的连接。如果您优化该连接,最终的 DELETE 也会更快。

          确保您在进行连接的列上有索引。运行执行计划以确保它们正在被使用。

          【讨论】:

            【解决方案7】:

            清理完数据后,我会在 table3 上放置一个 AFTER DELETE 触发器,它会自动从 table1 中删除适用的记录。通过这种方式,您可以实时清理数据,而无需删除大块数据。

            【讨论】:

              【解决方案8】:

              我会创建一个临时表,创建一个选择并填充临时表,向临时表添加索引并从我的表中删除我想要从中删除记录的表。然后当我完成这样的事情时,我会放弃我的临时表

              Select * into #temp from mytable 
              

              在哪里等等(或您的查询)

              //如果需要,添加约束

              我只是将主键推到临时表中

              那我就说

              删除我的表 主键在哪里(从#temp中选择myPrimarykey)

              【讨论】:

                猜你喜欢
                • 2015-12-31
                • 1970-01-01
                • 2014-03-25
                • 1970-01-01
                • 1970-01-01
                • 2011-04-26
                • 1970-01-01
                • 2021-08-07
                • 2020-08-10
                相关资源
                最近更新 更多