2011-06-15 258 views
2

我有兩個表。表2包含更新的記錄。 表1有900K記錄和表2大致相同。要執行SQL查詢需要很長時間

要執行下面的查詢大約需要10分鐘。大多數查詢(在執行下面的查詢時)到表1給出超時例外。

DELETE T1 
    FROM Table1 T1 WITH(NOLOCK) 
    LEFT OUTER JOIN Table2 T2 
    ON T1.ID = T2.ID 
    WHERE T2.ID IS NULL AND T1.ID IS NOT NULL 

有人可以幫我優化上面的查詢或寫更有效的東西嗎? 另外如何解決超時問題的問題?

+2

的數據庫引擎(SQL服務器?)?桌上有什麼索引? – 2011-06-15 01:43:19

+0

SQL服務器。我是否需要在兩個表中的ID列上添加索引? – 2011-06-15 01:46:00

+1

爲什麼「T1.ID不是NULL」永遠是假的?它在加入的LHS – 2011-06-15 01:46:06

回答

1

優化器可能會選擇阻止整個表,因爲如果需要刪除多個行,它更容易完成。在這樣的情況下,我以大塊的方式刪除。

while(1 = 1) 
begin 
    with cte 
    as 
    (
     select * 
     from Table1 
     where Id not in (select Id from Table2) 
    ) 
    delete top(1000) cte 

    if @@rowcount = 0 
     break 

    waitfor delay '00:00:01' -- give it some rest :) 
end 

所以查詢一次刪除1000行。優化器可能會鎖定一個頁面來刪除行,而不是整個表。

該查詢執行的總時間將更長,但不會阻止其他呼叫者。

聲明:假定爲MS SQL。

另一種方法是使用SNAPSHOT事務。當行被刪除時,這種方式的表讀取器不會被阻塞。

+0

MS SQL對於標記爲「tsql」的問題確實是一個合理的假設;) – 2011-06-15 02:01:25

+0

Alex只想確認。你確定select語句與我的查詢結果相同嗎? – 2011-06-15 02:06:40

+0

我在兩個表上都添加了索引。嘗試執行您的查詢。在執行嘗試選擇一條記錄的時間內,會發出超時。你知道什麼是錯的嗎? – 2011-06-15 02:19:27

0

等一下,你想做到這一點...

DELETE Table1 WHERE ID NOT IN (SELECT ID FROM Table2) 

如果是這樣,那我就是這麼寫的。 您也可以嘗試更新兩個表上的統計信息。當然,Table1.ID和Table2.ID上的索引可以大大加快速度。

編輯:如果您從設計師獲取超時,增加SSMS中的「設計器」超時值(默認值爲30秒)。工具 - >選項 - >設計器 - >「覆蓋表設計器更新的連接字符串超時值」 - >輸入合理的數字(以秒爲單位)。

+0

我試圖在SSMS中添加索引,並且所有時間都超出鎖定請求超時期限 – 2011-06-15 01:51:22

+0

我更新了我的答案。 – 2011-06-15 02:00:06

0

兩個ID列需要指數

然後用簡單的SQL

DELETE Table1 WHERE NOT EXISTS (SELECT * FROM Table2 WHERE Table1.ID = Table2.ID) 
+0

我試圖運行您的查詢需要同一時間。表1中的大部分查詢都超時。我知道我做錯了什麼。它是一個生產數據庫,因此它有很多查詢 – 2011-06-16 14:25:35

+0

@Andrew Venture:索引? – gbn 2011-06-16 14:27:33

+0

是的,我在這兩個表上都有索引 – 2011-06-17 01:50:49