2016-12-08 5 views
0

Oracle 11Gに接続するEF6(モデルファースト)を使用しています。Entity Frameworkのlinqクエリが遅すぎる

私は3つのテーブルA、B、Cを持っている、と私は関係を得るために右FKを定義した:

1. B is a child of A. 
2. C is a child of B. 

は今、私は(熱心なロードを使用して)次のコードを実行していると取得しますBとC:

私が見ることができるように、私はincludeとselectを使って、BをB、CをCで熱心に検索します。

私の問題は、FirstOrDefault()メソッドを実行するのに約4秒かかります。

これをTOADでテストし、生成されたSQLを1秒未満で実行しました。

検索されたオブジェクト(Aが配置されている)はそれほど大きくはありません(Aは5 Bを持ち、Bは2 Cを持ち、各テーブルは〜10列です)。

パフォーマンスを向上させる方法はありますか?

+0

テーブルにはいくつのレコードがありますか? –

+0

これはアプリケーションが実行する最初のクエリですか? EFの最初のクエリには常に時間がかかります。ステートメントをもう一度実行してみてください。これははるかに速くなければなりません。 – Daniel

+0

Aレコードは100レコードです。 Bには〜3000件のレコードがあります。 Cには〜1000件のレコードがあります。 結果は約20レコード(3つのテーブルすべてから)です。 これは最初の実行ではありません(私は2回実行しようとしましたが、まだパフォーマンスは悪くなっています) – Nir

答えて

0

私はあなたのケースで.Include(a => a.B.Select(y => y.C))ではなく、あなたが(一般的に)最も子孫テーブルからSELECTが最初に、その後、INNER JOIN任意の親にIncludeを使用する必要があり、最適ではない、あなたの結果セット内の行ごとに別の独立したSELECTを実行することを考えますあなたが必要とするデータ。

は、代わりにこのクエリを試してみてください。また、

var query = context.C 
    .Include(c => c.B) 
    .Include(c => c.B.A) 
    .Where(c => c.B.A.sku == 2); 
return query.FirstOrDefault(); 

を、あなたのインデックスをチェック。

+0

'Include(x => xBSelect(y => yC))'はEF6のように、 'インクルード(" BC ")'あなたが提案しているものは、有効な構文ではありません。 –

+0

@IvanStoev私は自分のプロジェクトに 'Include(first => first.Second.Third)'を使っています。私はスコープ内に 'DbExtensions'を付けてEF6を使っています。 – Dai

+0

'Second'がコレクション型であることを確認してください。つまり、first(one) - > second(many) - > third(one)です。 OPのサンプルでは、​​ 'x.B'が単一のオブジェクトであれば、' Select'はコンパイルされません。 –

0

最終的に、遅さの問題を解決するために、私が興味を持っていた列だけを選択し、それをDTOに入れました。

var myQuery = from r in MyContext.A 
          .Include(x => x.B.Select(y => y.C)) 
          .Where(a => a.sku == 2) 
           Select new MyDTO 
           { 
           ... 
           } 
var res = myQuery.FirstOrDefault(); 
+0

.AsNoTracking()もチェックしてください。リストが変更検出を必要としない場合はAsNoTrackingが高速化する可能性がありますが、逆に同じコンテキストで同じエンティティを繰り返し照会している場合は、実際に変更追跡を有効にすることでパフォーマンス上のメリットが得られます。 – richardb

関連する問題