1

私は現在、エンティティフレームワークを使用する(4.0バージョンの)既存のc#プロジェクトのパフォーマンスを改善する過程にあります。アプリケーションで実行される一括操作には、次の2種類があります。

  1. バルクインサート
  2. 一括削除

現在、これらは純粋なSQLステートメント( "INSERT INTO ..."、 "DELETE FROM ...")を使用して実行されます(挿入ステートメント自体は現在、一括挿入ステートメントではなく、代わりに「通常の」挿入ステートメントです)。

私はC#にかなり慣れていないので、最初のステップは、更新と削除にエンティティフレームワークを使用した場合のパフォーマンスを確認することでした。

ここでの私の質問は3つに分かれています。

  1. エンティティフレームワークで一括挿入を実行しようとすると、挿入されたデータ行ごとに1つの挿入が使用されるというのは本当ですか?(したがって、各インサートの往復)。したがって、パフォーマンスはSQLの「挿入」を使用するよりも低くなりますか?
  2. これは削除ステートメントにも当てはまりますか?
  3. ここでのベストプラクティスは何ですか?SQLステートメントを使用するには?または、エンティティフレームワーク、または他の何かを完全に使用するには?

(データ行については、それぞれ2k〜200kのサイズについて話しています)。

ありがとう

4

2 に答える 2

2

ここでの私の質問は3つに分かれています。

エンティティフレームワークで一括挿入を実行しようとすると、挿入されたデータ行ごとに1つの挿入が使用されるというのは本当ですか?(したがって、各インサートの往復)。したがって、パフォーマンスはSQLの「挿入」を使用するよりも低くなりますか?

はい。EFを使用する場合は、次のプロパティをfalseに設定して、パフォーマンスを高速化します。

MyContext.Configuration.AutoDetectChangesEnabled = false;
MyContext.Configuration.ValidateOnSaveEnabled = false;

これは削除ステートメントにも当てはまりますか?

はい。また、データベースで「カスケードの削除」を定義すると、データベースは参照されたエンティティを削除するため、EFを使用してこれを行う必要はありません。

ここでのベストプラクティスは何ですか?SQLステートメントを使用するには?または、エンティティフレームワーク、または他の何かを完全に使用するには?

ストアドプロシージャを使用して、コンテキストでクエリを呼び出すことができます

MyContext.ExecuteStoreQuery("your query")

また

MyContext.Database.SqlCommand("your query"); 

SaveChanges()もう1つの方法は、バッチ(100、200のエンティティが追加または削除済みとしてマークされている)の後で呼び出し、エンティティがまだ接続されないようにコンテキストを破棄することです。次に、新しいコンテキストを作成してバッチを作成し、SaveChanges()もう一度呼び出します。

アップデート

私はこのアプローチを使用しませんでしたが、試してみることができます。

Generic ListのSqlBulkCopy(Entity FrameworkとNHibernateに便利)

以下の再利用可能な汎用バージョン。2.4秒で15kの挿入、または1秒あたり±6200行を生成しました。+-5750 rps(4つのファイル間で変更)の場合、4つのカタログ(39秒で224392行)にアップしました。

于 2012-11-10T13:17:42.720 に答える
2

本当にバルクデータを挿入したい場合は、おそらく使用したいと思うでしょうSqlBulkCopy。EFコンテキストが使用するのと同じトランザクションで使用できます。

EFは一括操作用に作成されていないため、ステートメントごとに1行のDMLアプローチは、大規模なセットには制限が厳しすぎる場合があります。これにより、多くのラウンドトリップとステートメントごとのオーバーヘッドが発生し、SQL Serverが一度に多くの行のクエリプランを最適化できなくなります。これは、ほとんどの場合、多くの小さなクエリよりも効率的です(たとえば、SQLServerはすべての行を適切に並べ替えます。そのインデックスは順次更新できます)。

EFを使用してバルクDMLを実行することにより、基本的にSQLServerに行ごとのDMLプランを使用するように強制します。

一括削除は、一時テーブルにキーを一括挿入してから、そのテーブルに結合するdeleteステートメントを実行することで処理できます。

于 2012-11-10T13:22:59.617 に答える