5

選択したメイン カテゴリのすべての子カテゴリに含まれるすべての製品を取得するには、どのような方法が最適でしょうか? 約 80 の子カテゴリで 10000 個の製品を取得しようとしていますが、この方法では遅すぎます。助言がありますか?C# と Linq to SQL の使用

//list for the child categories
private List<int> catsChildList = new List<int>();

GetChildCats(123);

//get all the child categories of main category '123'

private void GetChildCats(int _parentCat)
{
    var cats = (from c in db2.tbl_cart_categories
                where c.ParentID == _parentCat
                select new { c.CategoryID });
    if (cats.Count() > 0)
    {
        foreach (var cat in cats)
        {
            int _cat = Convert.ToInt32(cat.CategoryID);
            catsChildList.Add(_cat);
            GetChildCats(_cat);
        }
    }
}

//Get the products
var products = (from p in db2.products_infos
            where  p.IsEnabled == true
            group p by p.ProdID
            into g where g.Any(x => catsChildList.Contains(Convert.ToInt32(x.CategoryID)))

結果を返すのに約 6 秒かかります

4

4 に答える 4

3

違いは何ですか

var products = 
    (
     from p in db2.products_infos
     where  p.IsEnabled == true
     group p by p.ProdID
     into g where g.Any(x => catsChildList.Contains(Convert.ToInt32(x.CategoryID)))
     select g
    );

 var tmpList = 
    (
     from p in db2.products_infos
     where  p.IsEnabled == true 
            && catsChildList.Contains(Convert.ToInt32(p.CategoryID))) 
     select p
    ).ToList();

 var products = 
     (from r in tmpList group p by r.ProdID into g select g);

?

私のスキーマが違うのかもしれませんが、Linq2Sql でこれを試してみると同じ結果が返されるように見えますが、後者はすべて 1 つのデータベース ヒットで結果を返しますが、前者は複数のリクエストを発行します。(返された製品の数が 10000 の場合、10001 のデータベース要求を実行することになります)。

于 2012-04-04T17:11:12.767 に答える
2

提供された統計とコードに基づいて、次の行を削除して 3 秒節約する必要があります。

if (cats.Count() > 0)

...列挙を2倍にするため(そして、データベース呼び出しを2倍にしていることを考えると、それは完全に悪いことです) Count == 0の場合にクラッシュするものは何もないため、ほとんど無意味です.

MS SQL Server をヒットしている場合、追加のデータベース ヒットが表示される可能性が高いため、提供されている Profiler がここで役立ちます。

于 2012-04-04T16:06:39.730 に答える
0

まず、具体的には言いませんが、Linq to Sqlを使っていると仮定しています。その情報を含めるように質問を更新してください。

まず、いくつかの基本的なプロファイリングを追加します。実行に最も時間がかかっているクエリはどれですか?

g.Any(x => catsChildList.Contains(Convert.ToInt32(x.CategoryID)))

これは間違いなく疑わしいです。catChildList に多くの値がある場合、常に実行速度が遅くなる巨大な IN 句が生成される可能性があります。これは、実行中の実際の SQL ステートメントをチェックすることで確認できます。

真実は、アプリケーションですべての反復を実行しようとしている場合、このような再帰的な階層トラバーサルは決して効率的ではないということです。ストアド プロシージャを使用すると、パフォーマンスが大幅に向上します。

于 2012-04-04T16:32:43.283 に答える
0

を。次のコード行は、GetChildCats() メソッドによる最初の行のラムダ式置換です。

var findCatList = (List<int> parent) => {        
    from c in db2.tbl_cart_categories
            where  & c.ParentID == _parentCat
            select (db2.tbl_cart_categories.Any(cat=> cat.ParentID == c.CategoryID) ?
                findCatList(c.CategoryID)
                :new { c.CategoryID }                    
                )}

var catList = findCatList(123);

しかし、これでも再帰が行われますが、内部的に行われます。それをチェックしてください。もちろん、オブジェクトに基づいた、テストされていないコードです。

b. 他に試すことができると思うのは、db2.tbl_cart_categories を db2.tbl_cart_categories.AsParallel() に置き換えてみることができるということです。オブジェクト コンテキスト/データ コンテキストがこれでどのように動作するかはわかりません。しかし、db2 はコンテキスト オブジェクトではないので、パフォーマンスが向上すると確信しています。

于 2012-04-04T16:28:59.120 に答える