2012-02-09 38 views
1

通常,需要從表Nodes中刪除大約110K行,但它們的id沒有明確聲明,而是從另一個表中指定。從表中刪除行數Transact-SQL

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行和服務器不能刪除它們由於過期超時。還有什麼其他的方式可以做到嗎?

+0

請問您可以添加XML執行計劃(估計會做,或者使用'DELETE TOP(10)FROM Nodes ...') – gbn 2012-02-09 08:51:26

回答

1

像這樣的東西可能會有所幫助。它將刪除沒有關聯關係條目的所有節點。外連接應該比在子查詢中使用「not in」子句要快得多。

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

您可以嘗試通過添加TOP子句DELETE刪除節點分批而不是所有在一次:

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) 
+0

感謝,它似乎工作但出現了另一個問題, mashine有4GB)。 – LackOfKnowledge 2012-02-09 06:34:19

0

你不需要DINSTINCT這一點。它增加了不必要的開銷到刪除語句。

二,你爲什麼要使用臨時表?您是否嘗試過這些2個語句較小的塊組合成一個?:

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 
+0

所有相同的超時異常 – LackOfKnowledge 2012-02-09 06:42:43

+0

你有'Relations.node_id'和'Nodes.id'上的索引嗎? – 2012-02-09 06:45:09

+0

是Nodes.id甚至是主節點) – LackOfKnowledge 2012-02-09 06:56:17

3

如果你飼養的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觸發器嗎?
  • 你有需要檢查的節點的外鍵嗎?
+0

'Nodes'和'Relations'具有'1:n'的關係。這不會導致'Nodes'表中的行重複嗎? – 2012-02-09 08:11:00

+0

如果存在Nodes表的外鍵,這也不起作用。 – Serguei 2012-02-09 08:26:17

+0

@ypercube:可能,但一個DISTINCT將解決這個問題。我正在尋找一個概念,而不是可運行的代碼 – gbn 2012-02-09 08:47:34