2010-11-19 104 views
0

我想獲得社區對此的看法。如果我有一個嚴重限制DB/IO的進程,那麼使用Task Parallel庫並行化各個進程路徑有多聰明?並行化注意事項

我會用一個例子......如果我有一大堆的項目,我需要做下面的操作

  1. 查詢一個數據庫的項目列表
  2. 做一些聚合操作根據動態參數列表對某些項目進行分組。
  3. 對於每個分組結果,根據聚合結果查詢數據庫中的內容。
  4. 對於每個分組結果,執行一些數值計算(3和4會按順序發生)。
  5. 做一些插入和更新爲#的計算結果3
  6. 做每個項目的一些插入和更新返回在#1

按道理講,我可以並行成步驟#任務圖3,#5,#6作爲一個項目對前一個結果沒有影響。但是,每一個都會在數據庫(sql server)上等待,這很好,我知道我們只能在SQL服務器允許的情況下進行處理。

但是我想在邏輯上將任務分配到本地機器上,這樣它就可以像數據庫一樣快速地處理任務,而無需等待任何結果。我已經做了一些模擬原型,我用Thread.Sleeps替換了數據庫調用(我還嘗試了一些與.SpinWait相比更快的版本),並行版本是waaaaay,比當前的完全串行根本不平行。

我害怕的是在SQL服務器上施加了太多的壓力......在我走得太遠的路上,我有沒有考慮一些我應該考慮的事項?

回答

1

另一個選項將創建一個管道,以便第二組的步驟3與第一組的步驟4同時發生。如果您可以在步驟5重疊更新,那麼也要這樣做。這樣你就可以執行併發SQL訪問和處理,但不會對數據庫進行過度徵稅,因爲你只有兩個併發操作一次進行。

因此,您按順序執行步驟1和步驟2(我假定)獲取需要進一步處理的組的集合。然後。你的主線程開始:

for each group 
    query the database 
    place the results of the query into the calc queue 

第二個線程服務,結果隊列:

while not end of data 
    Dequeue result from calc queue 
    Do numeric calculations 
    place the results of the query into the update queue 

第三個線程的服務更新隊列:

while not end of data 
    Dequeue result from update queue 
    Update database 

System.Collections.Concurrent.BlockingCollection<T>是一種非常有效的隊列這種事情。

這裏的好處是,如果您可以通過添加多個計算線程或查詢/更新線程來擴展它(如果SQL Server可以處理更多併發事務)。

我在日常的合併/更新程序中使用了與此非常相似的東西,效果非常好。該特定進程不使用SQL服務器,而是使用標準文件I/O,但這些概念翻譯得非常好。

2

如果並行版本比串行版本快得多,我不會擔心SQL服務器上的壓力......除非您正在執行的任務與其他一些重要的或時間關鍵的也在數據庫服務器上執行的操作。

你的任務的描述不是很好受我的理解,但它幾乎聽起來像以上這些任務應該已經在數據庫中直接執行(我假設有細節,使這不可能的?)