web-dev-qa-db-ja.com

多数のレコードに対するエンティティフレームワークの仕組み

すでに未回答の質問が表示されています こちら

私の質問は-

EFは本当に大規模なアプリケーションの生産準備ができていますか?

これらの根本的な質問から生まれた質問-

  1. EFはすべてのレコードをメモリにプルし、クエリ操作を実行します。テーブルに約1000レコードがある場合、EFはどのように動作しますか?
  2. 簡単な編集の場合、レコードを編集して編集し、SaveChanges()を使用してdbにプッシュする必要があります
51
Abhijeet

同様の状況に直面しましたが、それぞれに7〜1000万レコードのテーブルが多数ある大規模なデータベースがありました。 Entity Frameworkを使用してデータを表示しました。素晴らしいパフォーマンスを得るために、私が学んだことは次のとおりです。 Entity Frameworkの私の10のゴールデンルール

  1. 実際のレコードが必要な場合にのみデータベースへの呼び出しが行われることを理解してください。すべての操作はクエリ(SQL)の作成に使用されるだけなので、大量のレコードを要求するのではなく、データの一部のみをフェッチしてください。可能な限りフェッチサイズをトリミングする

  2. はい、(場合によってはストアドプロシージャがより良い選択であり、一部の人があなたに信じさせるほど邪悪ではありません)、必要に応じてストアドプロシージャを使用する必要があります。それらをモデルにインポートし、それらの関数をインポートします。直接ExecuteStoreCommand()、ExecuteStoreQuery <>()を呼び出すこともできます。関数とビューについても同じことが言えますが、EFには関数 "SELECT dbo.blah(@id)"を呼び出すという奇妙な方法があります。

  3. EFは、エンティティに深い階層を設定する必要がある場合、パフォーマンスが低下します。深い階層を持つエンティティには非常に注意してください

  4. レコードを要求していて、それらを変更する必要がない場合、プロパティの変更を監視しないようにEFに指示する必要があります(AutoDetectChanges)。そうすれば、レコードの取得がはるかに高速になります

  5. データベースのインデックス作成は適切ですが、EFの場合は非常に重要になります。検索とソートに使用する列には、適切にインデックスを付ける必要があります。

  6. モデルが大きい場合、VS2010/VS2012モデルデザイナーは本当に夢中になります。モデルを中規模のモデルに分割します。異なるモデルのエンティティは、データベース内の同じテーブルを指している場合でも共有できないという制限があります。

  7. 異なる場所の同じエンティティで変更を行う必要がある場合は、同じエンティティを使用し、変更を加えて一度だけ保存します。重要なのは、同じレコードの取得を避け、変更を加えて複数回保存することです。 (実際のパフォーマンス向上のヒント)。

  8. 1列または2列だけの情報が必要な場合は、完全なエンティティを取得しないようにしてください。 sqlを直接実行するか、ミニエンティティを使用することができます。アプリケーションで頻繁に使用されるデータをキャッシュする必要がある場合もあります。

  9. トランザクションが遅い。それらに注意してください。

  10. SQLプロファイラまたはクエリプロファイラはあなたの友人です。アプリケーションの開発時に実行して、EFがデータベースに送信する内容を確認します。 urアプリケーションでLINQまたはLambda式を使用して結合を実行すると、EFは通常、常に適切に実行されるとは限らないSelect-Where-In-Selectスタイルのクエリを生成します。そのようなケースが見つかった場合は、スリーブをロールアップし、DBで結合を実行し、EFに結果を取得させます。 (私はこれを忘れました、最も重要なもの!)

これらのことを念頭に置いておくと、EFはプレーンADO.NETとほぼ同じパフォーマンスを提供するはずです。

130
Simple Fellow

1. EFはすべてのレコードをメモリにプルし、クエリ操作を実行します。テーブルに約1000レコードがある場合、EFはどのように動作しますか?

それは真実ではありません! EFは必要なレコードのみをフェッチし、クエリは適切なSQLステートメントに変換されます。 EFはDataContext内でローカルにオブジェクトをキャッシュできます(そしてエンティティに加えられたすべての変更を追跡します)が、必要な場合にのみコンテキストを開いたままにするというルールに従う限り、問題はありません。

2.簡単な編集のために、レコードを編集して編集し、SaveChanges()を使用してdbにプッシュする必要があります

本当ですが、パフォーマンスの問題が実際に見られない限り、私は気にしませんです。 1.は当てはまらないため、保存する前にDBから1つのレコードのみを取得します。 SQLクエリを文字列として作成し、プレーンな文字列として送信することで、これをバイパスできます。

19
MarcinJuraszek
  1. EFはLINQクエリをSQLクエリに変換するため、すべてのレコードがメモリにプルされるわけではありません。生成されたSQLが常に最も効率的であるとは限りませんが、1000レコードが問題になることはありません。
  2. はい、それはそれを行う1つの方法です(1つのレコードのみを編集したい場合)。複数のレコードを変更する場合、1つのクエリを使用してそれらすべてを取得でき、SaveChanges()はそれらの変更をすべて保持します。
6
Botz3000

EFは悪いORMフレームワークではありません。それは、独自の特性を持つ別のものです。 Microsoft Entity Framework 6と、Microsoft Enterprise Library 6を搭載したNetTiersとを比較してください。

これらは、まったく異なる2つの獣です。受け入れられた答えは、EF6のニュアンスを通過するので本当に良いです。理解すべき重要なことは、各ORMには独自の長所と短所があるということです。プロジェクトの要件とそのデータアクセスパターンをORMの動作パターンと比較します。

たとえば、NetTiersは常にEF6よりも高いパフォーマンスを提供します。ただし、それは主にポイントアンドクリックORMではなく、ORMの生成の一部として、データモデルを最適化すること、関連するカスタムストアドプロシージャを追加することなどです。同じデータモデルを設計した場合EF6の努力により、おそらく同じパフォーマンスに近づくことができます。

また、ORMを変更することを検討してください。たとえば、NetTiersを使用すると、コードスミステンプレートに拡張機能を追加して、ベースORMライブラリによって生成されるものの上に独自のデザインパターンを含めることができます。

また、EF6はリフレクションを大幅に活用する一方、NetTiersまたはMicrosoft Enterprise Libraryを搭載したライブラリはジェネリックを多用することを検討してください。これらは2つのまったく異なるアプローチです。なんでそうなの? EF6は動的反射に基づいているのに対し、NetTiersは静的反射に基づいているためです。どちらが高速でどちらが優れているかは、ORMに必要な使用パターンに完全に依存します。

ハイブリッドアプローチの方がうまく機能する場合があります。たとえば、Web API ODataエンドポイント用のEF6、カスタムストアドプロシージャを使用したNetTiersおよびMicrosoft Enterprise Libraryでラップされたいくつかの大きなテーブル、および初期ロードレコードセットは、ADOデータリーダーを使用してメモリキャッシュにストリーミングされます。

これらはすべて異なり、それぞれに最適なシナリオがあります:EF6、NetTiers、NHibernate、Wilson OR Mapper、Dev ExpressのXPOなど。

5
tcwicks

あなたの質問に対する簡単な答えはありません。主なことは、あなたがあなたのデータで何をしたいかについてですか?一度に大量のデータが必要ですか?

EFはクエリをSQLに変換したため、現時点ではメモリ内にオブジェクトはありません。データを取得すると、選択したレコードがメモリに格納されます。大量の大きなオブジェクトを選択している場合、それらすべてを操作する必要がある場合、パフォーマンスを低下させる可能性があります。

それらをすべて操作する必要がない場合は、変更追跡を無効にし、操作する必要がある単一のオブジェクトに対して後で有効にすることができます。

そのため、アプリケーションのタイプに応じて異なります。大量のデータを効率的に操作する必要がある場合は、ORマッパーを使用しないでください!

それ以外の場合はEFで問題ありませんが、一度に本当に必要なオブジェクトの数とそれらで何をしたいのかを考慮してください。

4
Dannydust