Sql-Server

使用大 IN 過濾器 VS 之間的事務級別差異。“開始傳輸/送出”

  • November 28, 2012

我想以最小的伺服器成本刪除大約 100,000 條記錄。我有一些嘮叨的問題我無法正確測試,所以我想我會在這裡問一些專家。哪個會更好:

1-

BEGIN TRAN
DELETE FROM dbo.x
WHERE ID IN (
1
,2
,3
,4
...
,100000
)
COMMIT

2-

BEGIN TRAN
DELETE FROM dbo.x
WHERE ID = 1
GO
DELETE FROM dbo.x
WHERE ID = 2
GO
...
COMMIT 

3-

DELETE FROM dbo.x
WHERE ID = 1
GO
DELETE FROM dbo.x
WHERE ID = 2
GO
...

我的假設是 #1 會根據樣本百分比進行掃描,挑選出項目,刪除它們,並將其記錄為一系列事務。也許它會將事務日誌中的資訊基於哪些頁面被更改而不是每個 indvl。事務,因此您只能回滾整個活動並重新標記頁面,或者您可以送出。那是對的嗎?

在 #2 上,我在想 GO 語句是否會導致更多的事務日誌活動,因為不允許 SQL Server 儲存引擎將所有這些都滾動到 1 個大事務中,但仍然使用 BEGIN TRAN 為事務日誌提供一些優化- COMMIT 塊,從而使其比#3 更有效,但不如#1 有效。

然後我會假設#3將是每個indvl中最糟糕的一個。交易被記錄。

如果有人有任何好的部落格文章或測試場景,他們可以指出我也會很棒。我已經研究過深入探勘事務日誌以自己弄清楚的方法,但在這一點上,我想我會問你們。

謝謝!

從日誌記錄的角度來看,1 和 2 與在這兩種情況下您在單個事務中執行所有刪除的情況大致相同。在執行刪除時會有很多鎖定並且可能會阻塞。#3 是每批一個事務,因此使用者不會受到太大影響,並且事務日誌中會有很多小事務,而不是一個大事務。#2 和 #3 應該花費大約相同的時間來執行。#1 應該比 #2 和 #3 花費更少的時間,因為它只是一個命令,但是執行時間可能仍然會導致問題。

我可能想做這樣的事情。這將通過一次僅處理 1000 行來最小化需要發生的鎖定和阻塞。

SELECT NULL
WHILE @@ROWCOUNT <> 0
BEGIN
 DELETE TOP (1000) FROM dbo.x
 WHERE ID IN ( /* if possible use "BETWEEN 1 and 100000" instead*/
 1
 ,2
 ,3
 ,4
 ...
 ,100000
 )
END

引用自:https://dba.stackexchange.com/questions/29461