2

私は次のクエリを持っています:

if (idUO > 0)
{
    query = query.Where(b => b.Product.Center.UO.Id == idUO);
}
else if (dependencyId > 0)
{
    query = query.Where(b => b.DependencyId == dependencyId );
}
else
{
    var dependencyIds = dependencies.Select(d => d.Id).ToList();

    query = query.Where(b => dependencyIds.Contains(b.DependencyId.Value));
}

[...] <- Other filters...

if (specialDateId != 0)
{
    query = query.Where(b => b.SpecialDateId == specialDateId);
}

したがって、このクエリには他のフィルターがありますが、最後に、データベース内のクエリを次のように処理します。

return query.OrderBy(b => b.Date).Skip(20 * page).Take(20).ToList(); // the returned object is a Ticket object, that has 23 properties, 5 of them are relationships (FKs) and i fill 3 of these relationships with lazy loading

最初のにアクセスするpageと、OK、クエリは1秒未満かかりますが、ページ30000にアクセスしようとすると、クエリに20秒以上かかります。linqクエリには、クエリのパフォーマンスを向上させる方法がありますか?それともデータベースレベルでのみですか?そして、データベースレベルでは、この種のクエリの場合、パフォーマンスを向上させるための最良の方法はどれですか?

4

4 に答える 4

2

ここには、物事を改善するためのスペースがあまりありません(少なくとも提供されているコードを見てください)。

このような数値で良好なパフォーマンスを達成しようとしている場合は、まったく使用 LINQしないか、データアクセスが少ないもので使用することをお勧めします。

ここでできることは、そのデータのページングをDataBaseレベルで導入stored procedureし、コードから呼び出すことC#です。

于 2012-08-31T12:27:24.440 に答える
1

1-製品などの関連するすべての関係を含む日付でアイテムを注文するビューをDBに作成します。

2-関連するパラメータを使用してこのビューをクエリするストアドプロシージャを作成します。

于 2012-08-31T12:31:35.413 に答える
1

SQL Server Profilerをプルアップし、クエリの実行中にサーバー上でプロファイルを実行することをお勧めします(高速と低速の両方)。これを実行したら、それをデータベースエンジンチューニングアドバイザーにプルして、追加する必要のあるインデックスに関するヒントを取得できます。これは、過去に私にとって大きな効果がありました。もちろん、必要なインデックスがわかっている場合は、Advisorを実行せずにインデックスを追加できます:)

于 2012-08-31T12:35:38.627 に答える
0

データベースでボトルネックが発生していることがわかると思います。これが理由です。

クエリ。

クエリと基準があります。それはかなり醜いが、それほどひどいselectステートメントでデータベースに行きます。

.OrderBy(b => b.Date)

今、あなたはこの巨大なレコードセットを日付で注文しています。これは、(うまくいけば)そのフィールドにインデックスが付けられているため、おそらくひどいヒットではありませんが、それは、スキップまたは取得する前に、セット全体がメモリに取り込まれ、ソートされることを意味します発生します。

.Skip(20 *ページ).Take(20)

さて、ここが貧弱なデータベースにとって大雑把なところです。大規模なレコードセットの場合、エンティティはこの種のことでかなりひどいです。私はあなたがSQLプロファイラーを開いて、それが送信しているSQLのランダムな混乱を見るのをあえてします。

スキップして取得を開始すると、Entityは通常、データベースに、探しているものが見つかるまで巨大なレコードセット全体をスキャンするように強制するクエリを送信します。それがレコードセットで最初に注文されたレコード、たとえば1ページ目である場合、それほど長くはかからない可能性があります。30,000ページを選択するときまでに、エンティティがステートメントを準備した方法が原因で、大量のデータをスキャンしている可能性があります。

次のリンクをご覧になることを強くお勧めします。2005年と書いてありますが、2008年にも当てはまります。

http://www.codeguru.com/csharp/.net/net_data/article.php/c19611/Paging-in-SQL-Server-2005.htm

そのリンクを読んだら、目的を達成するためにストアドプロシージャを作成する方法を検討することをお勧めします。より軽量になり、実行プランがキャッシュされ、データをはるかに高速に返すことが保証されます。

それを除けば、LINQを使い続けたい場合は、コンパイルされたクエリを読み、読み取り専用操作にMergeOption.NoTrackingを設定していることを確認してください。また、特に結果を繰り返し処理して他のテーブルに結合している場合は、読み込みを延期したIQueryableではなく、明示的な結合を使用してオブジェクトクエリを返すようにしてください。遅延ロードは、実際のパフォーマンスキラーになる可能性があります。

于 2012-08-31T14:53:38.203 に答える