2011-08-24 19 views
5

これは、技術的な "ハウツー"または "最良のアプローチ"の問題です。C#LINQと大規模なデータセットを含む計算

データベースからレコードを取得し、それらを「メモリ内」リストに配置し、そのデータに対して最大値、平均値、およびさらに特定のカスタム統計値などの一連の計算を実行するという現在の要件があります。

私たちがORMとしてNHibernateを使用し、データベースからデータを取得する優れた仕事をしているので、 'メモリ内'リストにデータを取得することは問題ではありません。私が求めているアドバイスは、データの結果のリストに対してどのように計算を行うべきかということです。

理想的には、MaximumValue()、AverageValueUnder100()、MoreComplicatedStatistic()などの各統計についてメソッドを作成したいと思います。もちろん、各メソッドに必要な変数を渡して結果を返すこともあります。このアプローチはまた、単体テストを楽にし、優れたカバレッジを提供します。

計算ごとにLINQクエリを実行するか、可能な限り少数のLINQクエリで各統計メソッドへの呼び出しを多数集約する必要があります。たとえば、AverageValueBelow100というメソッドにデータのリストを渡し、1つのLINQクエリで効果的に実行できるときは、データリスト全体を別のメソッドAverageValueBelow50に渡すことはあまり意味がありません。

パフォーマンスを犠牲にすることなく、高度な粒度と分離を達成するにはどうすればよいですか?

アドバイス...質問は十分に明確ですか?

+4

パフォーマンスを向上させるためにインデックスの利点があるデータベースに対してクエリを実行するのが最適な方法です –

+0

本当ですか?したがって、「メモリー内」を処理するのではなく、データベースを照会する方が良いでしょう。計算のいくつかは非常に複雑なので、これが最良のアプローチであるとは必ずしも思えません。 – Rowen

+1

ほとんどの場合、データベースの方が速い –

答えて

1

計算の複雑さによっては、データベースで実行するのが最適かもしれません。非常に複雑で、オブジェクトとして持ち込む必要があり、オーバーヘッドが発生する場合は、結果セットに対して複数の反復を避けたい場合があります。 Aggregateの使用を検討することをお勧めします。それについては、http://geekswithblogs.net/malisancube/archive/2009/12/09/demystifying-linq-aggregates.aspxを参照してください。それぞれの集計を個別に単体テストできますが、1回の反復で複数の集計を(潜在的に)投影できます。

1

「データベース内ですべてを行うのがベスト」と私は同意しません。

よく書かれたLinqクエリは、データベースに対して実行される良好なSQLクエリをもたらします。これは、パフォーマンス面で十分に優れているはずです(dwhを実行しない場合)。これは、Linq Provider for NHibernateを使用していて、Linqをオブジェクトに使用していないことを前提としています。

いいですね、簡単に変更でき、ビジネスロジックを1か所に保持できます。

あなたの必要に応じて遅すぎる場合は、作成された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メンバーのみを使用していましたが、これは、DataRow、Entities、または何を使用しないかを提案していないためです。私はその件についてもっと知っている他の人々にそれを残すでしょう!

関連する問題