私はムービーストアのWebサイト(ASP.NET、EF4、SQL Server 2008を使用)に何か設定しようとしています。私のシナリオでは、 "Member"ストアがActorName、MovieTitle、およびCatalogNumberを含むテキストファイルには、次のようにEF4何千ものレコードをインポート/ルックアップ - 私のパフォーマンスが悪臭を放つ!
俳優、映画、CatalogNumber
ジョン・ウェイン、勇気ある追跡、4577から12(レコードごとに繰り返される)
このデータはに使用されますが俳優や映画を検索し、「MemberMovie」レコードを作成します。これらのテーブルを使用して100以上のレコードをインポートすると、インポート速度がひどいです:
- 俳優表:フィールド= {ID、名前、等}
- 映画表:フィールド= {ID、タイトル、アクターID、等}
- MemberMovie表:フィールド= {ID、CatalogNumber、MOVIEID次のように(ファイルが正常にアップロードされた後)、テキストファイルからMemberMovieテーブルにデータをインポートするなど}
私の方法は次のとおりです。
- コンテキストを作成します。
- ファイル内の各行について、Actorテーブルでアーティストを参照します。
- Artistテーブルの各ムービーについて、一致するタイトルを検索します。
- 一致するMovieが見つかった場合は、コンテキストに新しいMemberMovieレコードを追加し、ctx.SaveChanges()を呼び出します。
私の実装のパフォーマンスはひどいです。私の期待は、これが数秒で(ファイルがアップロードされた後に)何千ものレコードで行えるということです。
私の質問はです:このようなバルク検索/挿入を実行する最適な方法は何ですか?新しく作成されたMemberMovieではなく、SaveChangesを一度呼び出す必要がありますか?ストアドプロシージャのようなものを使ってこれを実装する方が良いでしょうか?
私のループのスニペットは、おおよそこの(簡潔にするために編集)です:
while ((fline = file.ReadLine()) != null)
{
string [] token = fline.Split(separator);
string Actor = token[0];
string Movie = token[1];
string CatNumber = token[2];
Actor found_actor = ctx.Actors.Where(a => a.Name.Equals(actor)).FirstOrDefault();
if (found_actor == null)
continue;
Movie found_movie = found_actor.Movies.Where(s => s.Title.Equals(title, StringComparison.CurrentCultureIgnoreCase)).FirstOrDefault();
if (found_movie == null)
continue;
ctx.MemberMovies.AddObject(new MemberMovie()
{
MemberProfileID = profile_id,
CatalogNumber = CatNumber,
Movie = found_movie
});
try
{
ctx.SaveChanges();
}
catch
{
}
}
すべてのヘルプは歓迎です!
おかげで、デニス
EFのこの種のタスクのパフォーマンスが低いです。 EFは一括操作をサポートしていないため、インポート、マイグレーションなどはすべて遅いです。最初にテーブルにインデックスを追加し、DBへのラウンドトリップ数を減らそうとします。たとえば、John Wayneと50のレコードがある場合、Actorテーブルと関連するすべてのMoviesを50回クエリします。アルゴリズムの再定義が必要になります。必要なすべてのアクターを一緒にロードすることもできます。処理時間は短縮されますが、実際の処理とメモリ負荷は増加します。 –