2010-02-18 17 views
1

這是關於MS SQL Server 2005的我應該打破大型SQL查詢(MS)

我有一個SSIS包驗證兩個不同的數據源之間的數據。如果發現不同,它會構建並執行SQL更新腳本來解決問題。找到所有差異後,SQL Update腳本將在軟件包的末尾運行。

我想知道是否有必要或一個好主意,如何將SQL更新腳本分解成多個事務,最好的辦法是做到這一點。

更新腳本類似於此,但更長(例如):

Update MyPartTable SET MyPartGroup = (Select PartGroupID From MyPartGroupTable 
Where PartGroup = "Widgets"), PartAttr1 = 'ABC', PartAttr2 = 'DEF', PartAttr3 = '123' 
WHERE PartNumber = 'ABC123'; 

對於每一個錯誤/差分發現一個額外的更新查詢添加到更新腳本。我只預計每天會有300次更新,但有時可能會有5萬次。我是否應該將腳本分解爲每500個更新查詢等事務?

回答

1

您的系統會處理讀取尚未更新的數據的其他進程嗎?如果是這樣,你可能想要執行多個事務。

執行多個事務的好處是您不會持續累積鎖。如果您一次執行所有這些更新,SQL Server將最終用盡小型鎖資源(行/鍵)並升級到表鎖。當它這樣做時,在事務完成之前(除非它們使用髒讀或處於快照模式),否則沒有人能夠從這些表中讀取數據。

副作用是讀取數據的其他進程可能會得到不一致的結果。

因此,如果nodoby在更新時需要使用這些數據,那麼一定要在一個事務中執行所有更新。如果還有其他進程需要使用該表,那麼是的,分塊進行。

+0

這將在沒有人使用該系統時運行,但感謝您的解釋。對於未來的知識,當你說大塊的話是否你說有多個交易? 類似於: BEGIN TRANSACTION; //寫下500件東西 COMMIT TRANSACTION; BEGIN TRANSACTION; //寫下500件東西 COMMIT TRANSACTION; BEGIN TRANSACTION; //寫下500件東西 COMMIT TRANSACTION; – MaxGeek

+1

是的,我的意思是在多個事務中執行更新,如果你想避免表鎖。另一個考慮:如果更新索引列,則每個更新都會觸發對索引的更新。如果是這樣,在完成所有這些更新之後,您可能需要重新對該表進行索引並更新其中的統計信息。 –

1

這不應該是一個問題分解的事情。但是,如果您希望A.維護項目之間的一致性,和/或B.稍微好一些,您可能希望爲while事件使用單個事務。其中程序邏輯將通過分割查詢一但其中的多個動作之間的數據一致性期望更加清晰 -

BEGIN TRANSACTION; 
//Write 500 things 
//Write 500 things 
//Write 500 things 
COMMIT TRANSACTION; 

交易因爲這個原因存在。

2

不,我認爲這種說法很好。它根本不會在速度上產生太大的差異。 Billy如果您關心查詢的可讀性(如果這是將來可以查看或使用的查詢,那麼您應該這麼做)提供了一個有效的觀點。

2

在知道存在問題之前,不會優化任何內容。如果它運行得很快,就放手吧。如果運行緩慢,請進行一些更改。

+0

+1:用於識別過早優化。錯 - 沒有選票,但我會回來! –

1

如果事務在隔離級別爲SNAPSHOT,則受查詢影響的所有記錄將被鎖定或複製到tempdb

如果記錄數足夠高,鎖定可能會升級。

如果事務隔離級別不是SNAPSHOT,那麼併發查詢將無法讀取鎖定的記錄,這可能是您的應用程序的併發問題。

如果事務隔離級別爲SNAPSHOT,那麼tempdb應該包含足夠的空間來容納舊版本的記錄,否則查詢將失敗。

如果這對你來說是個問題,那麼你應該把更新分成幾個塊。