現在、私はかなり複雑なデータベースに取り組んでいます。オブジェクト モデルは、データベースにマップされるように設計されています。手動で生成された POCO クラスで EF 5 を使用しています。
すべてが機能していますが、パフォーマンスについて不満があります。EF でパフォーマンスの問題が発生したことは一度もないので、今回はひどく間違ったことをしただけなのか、それとも問題が別の場所にあるのか疑問に思っています。
メインクエリは、動的パラメータで構成されている場合があります。概念的には次のような if ブロックと switch ブロックがいくつかあります。
if (parameter != null) { query = query.Where(c => c.Field == parameter); }
また、いくつかの複雑な And/Or の組み合わせについては、Albahari の LinqKit 拡張機能を使用しています。
クエリは、年と年のデータを含む「注文」の大きなテーブルに対して行われます。ただし、平均的な使用は2か月の範囲フィルターです。
メイン クエリが作成されるとSkip/Take
、Take が 10 要素に設定された組み合わせでページ分割されます。
このすべての後、IQueryable はレイヤーを介して送信され、Automapper が使用される MVC レイヤーに到達します。
ここで、Automapper が反復を開始する (したがって、クエリが実際に実行される) と、独自のナビゲーション プロパティなどを持つ一連のナビゲーション プロパティが呼び出されます。含めるエンティティが 3 つまたは 4 つを超える場合は、積極的な読み込みを避けるために、すべてが EF の推奨事項に従って遅延読み込みに設定されます。私のシナリオは次のようなものです:
- 注文 (最大 10)
- Order の下の多くのナビゲーション プロパティ
- これらの一部には、その下に他のナビゲーションがあります (ローカリゼーション エンティティ)
- 注文の詳細 (注文ごとに多くの注文の詳細)
- 各注文詳細の下にある多数のナビゲーション プロパティ
- これらの一部には、その下に他のナビゲーションがあります (ローカリゼーション エンティティ)
- 各注文詳細の下にある多数のナビゲーション プロパティ
- Order の下の多くのナビゲーション プロパティ
これにより、1 つのレンダリングされた「ページ」に対して合計 300 以上のクエリが簡単に発生します。これらの各クエリは非常に高速で、数ミリ秒で実行されますが、それでも 2 つの主な懸念事項があります。
- 遅延ロードされたプロパティは順番に呼び出され、並列化されないため、より多くの時間がかかります
- 前のポイントの結果として、データベースはクエリごとに sql を受け取り、実行し、返す必要があるため、各クエリの間にデッドタイムがあります。
それがどのように行われたかを確認するために、熱心な読み込みで同じクエリを作成しようとしましたが、予想どおり、翻訳された SQL は 7,000 行 (はい、7,000 行) を超え、全体的にはるかに遅くなりました。
このシナリオでは、EF と Linq が適切な選択ではないとは考えたくありません。必要なデータをすべてフェッチするストアド プロシージャを作成すると、数十倍速く実行されると言う人もいます。私はそれが真実であるとは信じていません.関連するすべてのエンティティの自動実体化を失うことになります.
次のように、改善するためにできることをいくつか考えました。
- 選択した列を減らすためのテーブル分割
- このシナリオは読み取り専用であるため (追跡されていないエンティティがあるため)、オブジェクトの追跡をオフにします。
これらすべてを踏まえると、主な不満は、結果ページ (MVC 4 で実行) のレンダリングが遅すぎることです。少し診断した後、「ネットワーク時間」ではなく「サーバー時間」のように見え、約 8 から 12 かかります。サーバー時間の秒。
私の経験から、これは起こるべきではありません。このクエリの必要性に間違った方法でアプローチしているのか、それとも他の何かに注意を向ける必要があるのか 疑問に思っています(おそらく、設定が不適切なIISサーバー、または私が本当に無知な何か)。言うまでもなく、データベースのインデックスは正常であり、DBA によって非常に注意深くチェックされています。
したがって、誰かがこれについて見逃しているヒント、アドバイス、ベストプラクティスを持っている場合、またはこのシナリオで遅延読み込みを使用して EF を使用するのは完全に間違っていると言うことができます...大歓迎です。