【问题标题】:Delete number of rows from table Transact-SQL从表 Transact-SQL 中删除行数
【发布时间】:2012-02-09 06:04:22
【问题描述】:

通常需要从表 Nodes 中删除大约 110K 行,但它们的 id 没有明确声明,而是从另一个表中给出的。

DECLARE @gh Table(id int);
INSERT INTO @gh (id) SELECT node_id FROM Relations;
DELETE FROM Nodes WHERE id NOT IN (SELECT DISTINCT id FROM @gh)

选择 (SELECT DISTINCT id FROM @gh) 包含大约 20K 行,由于超时过期,服务器无法删除它们。还有什么其他的方法吗?

【问题讨论】:

  • 能否添加XML执行计划(估计可以,或者使用DELETE TOP (10) FROM Nodes ...

标签: sql-server sql-server-2008 tsql


【解决方案1】:

如果你保留 130k 中的 20k,我会以不同的方式进行

SELECT N.* 
  INTO #NodesTemp 
FROM  
  Relations R JOIN Nodes N ON R.id = N.id;

TRUNCATE TABLE Nodes;

INSERT Nodes SELECT * FROM #NodesTemp;

DROP TABLE #NodesTemp;

编辑:

  • 节点上有 DELETE 触发器吗?
  • 您是否有需要检查的节点的外键?

【讨论】:

  • NodesRelations 具有 1:n 关系。这不会导致Nodes 表中的行重复吗?
  • 如果节点表有外键,这也不起作用。
  • @ypercube:可能,但 DISTINCT 会解决这个问题。我要的是一个概念,而不是可运行的代码
  • @Serguei: 是的,但你可以DELETE in batches with no JOIN 或重命名表等
【解决方案2】:

您可以尝试通过在 DELETE 中添加 TOP 子句来批量删除节点,而不是一次全部删除:

WHILE EXISTS(SELECT * FROM Nodes WHERE id NOT IN (SELECT DISTINCT id FROM @gh))
DELETE TOP (100) Nodes
WHERE id NOT IN (SELECT DISTINCT id FROM @gh)

【讨论】:

  • 谢谢,它似乎可以工作,但出现了另一个内存量不足的问题(mashine 有 4GB)。
【解决方案3】:

这样的事情可能会有所帮助。它将删除没有相关关系条目的所有节点。外连接应该比在子查询中使用“not in”子句要快得多。

delete n
from Nodes n left outer join Relations r on n.id = r.node_id
where r.node_id is null

【讨论】:

    【解决方案4】:

    您不需要DINSTINCT。它给删除语句增加了不必要的开销。

    其次,为什么要使用临时表?您是否尝试过将这两个语句合二为一?:

    DELETE 
    FROM Nodes 
    WHERE id NOT IN 
          (SELECT node_id FROM Relations)
    

    或删除小块中的行,如@Serguei 建议的那样:

    SELECT 1
    
    WHILE @@ROWCOUNT > 0
    BEGIN
        DELETE TOP (1000)
        FROM Nodes 
        WHERE id NOT IN 
              (SELECT node_id FROM Relations)
    END
    

    【讨论】:

    • 都是一样的超时异常
    • Relations.node_idNodes.id 上有索引吗?
    猜你喜欢
    • 2016-12-17
    • 2018-04-02
    • 1970-01-01
    • 2017-08-28
    • 1970-01-01
    • 1970-01-01
    • 2019-12-25
    • 1970-01-01
    • 2020-08-06
    相关资源
    最近更新 更多