3

この仮想的な多対多の関係があるとします。

public class Paper
{
  public int Id { get; set; }
  public string Title { get; set; }
  public virtual ICollection<Author> Authors { get; set; }
}

public class Author
{
  public int Id { get; set; }
  public string Name { get; set; }
  public virtual ICollection<Paper> Papers { get; set; }
}

LINQ を使用して、他の著者と比較した各著者の「人気」を得るクエリを作成したいと考えています。これは、著者が貢献した論文の数を、すべての論文全体で一般的に著者の貢献の総数で割ったものです。これを達成するために、いくつかのクエリを考え出しました。

オプション1:

var query1 = from author in db.Authors
             let sum = (double)db.Authors.Sum(a => a.Papers.Count)
             select new
             {
               Author = author,
               Popularity = author.Papers.Count / sum
             };

オプション 2:

var temp = db.Authors.Select(a => new
           {
             Auth = a,
             Contribs = a.Papers.Count
           });
var query2 = temp.Select(a => new
             {
               Author = a,
               Popularity = a.Contribs / (double)temp.Sum(a2 => a2.Contribs)
             });

基本的に、私の質問は次のとおりです。これらのうちどれがより効率的であり、より効率的な他の単一クエリはありますか? 次のように、これらのいずれかを 2 つの個別のクエリと比較するとどうなりますか。

double sum = db.Authors.Sum(a => a.Papers.Count);
var query3 = from author in db.Authors
             select new
             {
               Author = author,
               Popularity = author.Papers.Count / sum
             };
4

2 に答える 2

0

まず第一に、それらを自分で試してみて、たとえばどれが最も時間がかかるかを確認できます.

最初に探す必要があるのは、これらの計算を適用するためだけにデータがすべてメモリにロードされないように、それらが完全に SQL に変換されるか、可能な限り近い形で変換されることです。

しかし、貢献したページの合計をキャッシュするための最適化をもう 1 つ行うと、オプション 2 が最善の策になると思います。このようにして、とにかく必要な作成者を取得するために db を 1 回呼び出すだけで、残りはコードで実行され、そこで並列化して高速化するために必要なことを実行できます。

次のようなものです (申し訳ありませんが、Linq を書くには流暢なスタイルを好みます):

//here you can even load only the needed info if you don't need the whole entity.
//I imagine you might only need the name and the Pages.Count which you can use below, this would be another optimization.
var allAuthors = db.Authors.All(); 

var totalPageCount = allAuthors.Sum(x => x.Pages.Count);

var theEndResult = allAuthors .Select(a => new
         {
           Author = a,
           Popularity = a.Pages.Count/ (double)totalPageCount
         });
于 2013-02-21T07:54:24.970 に答える
0

オプション 1 と 2 は、同じ SQL コードを生成する必要があります。読みやすくするために、オプション 1を使用します。
オプション 3 は 2 つの SQL ステートメントを生成し、少し遅くなります。

于 2013-02-21T08:43:26.523 に答える