2011-08-24 55 views
5

這更像是一個技術性的「如何操作」或「最佳方法」問題。C#LINQ和涉及大型數據集的計算

我們目前需要從數據庫中檢索記錄,將它們放入「內存」列表中,然後對數據執行一系列計算,即最大值,平均值和一些更具體的自定義統計數據。

將數據存入「內存中」列表並不成問題,因爲我們使用NHibernate作爲我們的ORM,它在從數據庫檢索數據方面表現出色。我正在尋求的建議是我們應該如何最好地對結果數據列表進行計算。

理想情況下,我想爲每個統計量MaximumValue(),AverageValueUnder100(),MoreComplicatedStatistic()等等創建一個方法。當然,將所需的變量傳遞給每個方法並返回結果。這種方法還可以使單元測試變得輕而易舉,併爲我們提供出色的覆蓋。

如果我們爲每個計算執行一次LINQ查詢,還是應該儘可能多地將每個統計方法的調用合併爲儘可能少的LINQ查詢,那麼會有性能問題嗎?例如,將數據列表傳遞給名爲AverageValueBelow100的方法並沒有什麼意義,然後將整個數據列表傳遞給另一個方法AverageValueBelow50,只要這些方法可以有效地用一個LINQ查詢執行。

如何在不犧牲性能的情況下實現高水平的粒度和分離?

任何建議......這個問題是否足夠清楚?

+4

最好的方法是對數據庫執行查詢,您可以從索引中獲益,從而提高性能 –

+0

真的嗎?所以不是處理「內存中」,我們最好查詢數據庫。一些計算相當複雜,所以我不完全確定這將是最好的方法。 – Rowen

+1

大多數數據庫都更快 –

回答

1

根據計算的複雜性,最好在數據庫中執行此操作。如果它非常複雜,您需要將其作爲對象引入並引發開銷,那麼您可能希望避免對結果集進行多次迭代。你可能要考慮使用Aggregate。如果需要討論,請參閱http://geekswithblogs.net/malisancube/archive/2009/12/09/demystifying-linq-aggregates.aspx。您將能夠單獨測試每個聚合,但是(可能)在單個迭代中投射多個聚合。

1

我不同意最好是「在數據庫中完成所有工作」。

編寫良好的Linq查詢將導致對數據庫執行良好的SQL查詢,這應該是足夠好的性能明智的(如果你不打算做dwh的東西)。這假設你正在使用NHibernate的Linq提供程序,而不是Linq的對象。

它看起來不錯,你可以很容易地改變它,並保持你的業務邏輯在一個地方。

如果這對於您的需求來說太慢了,您可能會檢查創建的SQL代碼並調整您的linq查詢,試圖預編譯它們,最後仍然可以返回編寫心愛的存儲過程並開始在各地傳播您的業務邏輯。

會有性能問題嗎?是的,你可能會失去幾毫秒,但這是否值得你爲分離你的邏輯付出代價?

+0

我並不是建議在數據庫中這樣做。我只是建議不要獲取內存中的所有數據,然後執行實際上是Linq的對象查詢。 –

0

要回答「我想爲每個統計量創建一個方法」的問題,我建議您建立一種統計學類。下面是一些僞代碼表達的想法:

class Statistician 
{ 
    public bool MustCalculateFIRSTSTATISTIC { get; set; } // Please rename me! 
    public bool MustCalculateSECONDSTATISTIC { get; set; } // Please rename me! 

    public void ProcessObject(object Object) // Replace object and Rename 
    { 
     if (MustCalculateFIRSTSTATISTIC) 
      CalculateFIRSTSTATISTIC(Object); 

     if (MustCalculateFIRSTSTATISTIC) 
      CalculateSECONDSTATISTIC(Object); 
    } 

    public object GetFIRSTSTATISTIC() // Replace object, Rename 
    { /* ... */ } 
    public object GetSECONDSTATISTIC() // Replace object, Rename 
    { /* ... */ } 

    private void CalculateFIRSTSTATISTIC(object Object) // Replace object 
    { /* ... */ } 
    private void CalculateSECONDSTATISTIC(object Object) // Replace object 
    { /* ... */ } 
} 

如果要我把要做到這一點,我可能會嘗試讓代表,而不是方法,它一般和使用的集合,但因爲我不知道您的上下文,我會留下來的。另外請注意,我只使用了對象類的Object成員,但這僅僅是因爲我並不建議您使用DataRows,Entities或其他東西;我會把它留給那些對我更瞭解這個主題的人們!