2009-05-27 105 views
6

我有一個Sql查詢,它返回了超過50萬行來處理......這個過程並不需要很長時間,但是我想用一些多處理來加快它的速度。考慮到下面的代碼,是否有可能輕鬆地多線程的東西?有沒有辦法多線程的SqlDataReader?

using (SqlDataReader reader = command.ExecuteReader()) 
{ 
    while (reader.Read()) 
    { 
     // ...process row 
    } 
} 

如果我能簡單地在結果列表的開頭和中間找到一個光標,那將是完美的。這樣,我可以有兩個線程處理記錄。然而,SqlDataReader不允許我這樣做...

任何想法我怎麼能實現這一點?

+0

如果您知道如何對查詢進行分區,則可以並行運行2個查詢。 – VVS 2009-05-27 14:01:20

回答

6

設置一個生產者/消費者隊列,其中一個生產者進程從閱讀器中拉出並儘可能快地排隊記錄,但不執行「處理」。然後一些其他的進程數量(你想要多少取決於你的系統)去出隊並處理每個排隊的記錄。

+0

嗯..奇怪,但我找不到已經實施的通用生產者/消費者模式。現在玩我自己的,但輸入這裏是讚賞:http://stackoverflow.com/questions/916863/generic-net-produce-consumer – 2009-05-27 17:03:02

0

它是一個簡單的範圍查詢,如1到500000之間的WHERE Id嗎?如果是這樣,您可以啓動N個查詢,每個查詢返回範圍的1/N。但它有助於瞭解單線程方法的瓶頸。如果您正在從一個磁盤主軸上進行連續讀取以完成查詢,那麼您應該使用單個線程。如果在一定範圍內跨主軸進行分區,則可以智能調整查詢以最大化磁盤的吞吐量(即從各個磁盤並行讀取各個查詢)。如果你期望所有的行都在內存中,那麼你可以隨意並行化。但是,如果查詢更復雜,那麼您可能無法輕鬆對它進行分區而不會產生一堆開銷。大多數情況下,上述選項並不適用,Joel提到的生產者/消費者將是唯一併行化的地方。取決於你花費每一行處理多少時間,這可能只會提供微不足道的收益。

3

您不應該在客戶端上讀取很多行。

也就是說,您可以將您的查詢劃分爲多個查詢,並行執行它們。這意味着在不同的線程中啓動多個SqlCommands,並讓它們每個都有一個結果分區。在A +問題是如何將結果劃分,而這在很大程度上取決於Ø您的數據和查詢:

  1. 可以使用一定範圍的密鑰
  2. 您可以使用屬性(如ID betweem 1 and 10000ID between 10001 and 20000等)。 (如:RecordTypeID IN (1,2)RecordTypeID IN (3,4)等)
  3. 您可以使用合成的範圍(即ROW_NUMBER() BETWEEN 1 and 1000等),但是這是一個很大的問題拉右
  4. 您可以使用散列(例如,BINARY_CHECKSUM(*)%10 == 0BINARY_CHECKSUM(*)%10==1等)

你只需要非常小心,分區查詢沒有重疊,並且塊在執行期間(即)。掃描相同的記錄並獲取X鎖),從而序列化彼此。

+0

我不認爲這是一個非常好的主意 - 開發人員不應該對這些數據非常瞭解(或將來可能會出現的情況)。另外,任何解決方案都應該可以在其他場景中重用。真正的多線程解決方案最好,就像上面提到的生產者/消費者一樣。 – 2011-01-12 19:11:24

相關問題