基本的に、1つのトランザクション内に35000個のオブジェクトを挿入します。
using(var uow = new MyContext()){
for(int i = 1; i < 35000; i++) {
var o = new MyObject()...;
uow.MySet.Add(o);
}
uow.SaveChanges();
}
これは永遠にかかります!基になるObjectContex
tを(IObjectAdapter
を使用して)使用すると、まだ遅いですが、約20秒かかります。 DbSet<>
は線形検索を行っていますが、これには時間がかかります...
この問題を見ている人はいますか?
コメントでLadislavが既に示したように、パフォーマンスを改善するには自動変更検出を無効にする必要があります。
context.Configuration.AutoDetectChangesEnabled = false;
この変更検出は、DbContext
APIでデフォルトで有効になっています。
DbContext
がObjectContext
APIと非常に異なる動作をする理由は、DbContext
APIの多くの関数がDetectChanges
の関数よりもObjectContext
を内部的に呼び出すためです。 $ var] _自動変更検出が有効な場合のAPI。
ここ デフォルトでDetectChanges
を呼び出す関数のリストを見つけることができます。彼らです:
Add
のAttach
、Find
、Local
、Remove
、またはDbSet
メンバーGetValidationErrors
のEntry
、SaveChanges
、またはDbContext
メンバーEntries
のDbChangeTracker
メソッド特に、Add
はDetectChanges
を呼び出します。これは、パフォーマンスの低下の原因となります。
これとは対照的に、ObjectContext
APIはDetectChanges
でのみ自動的にSaveChanges
を呼び出しますが、AddObject
および上記の他の対応するメソッドでは呼び出しません。これが、ObjectContext
のdefaultパフォーマンスが速い理由です。
なぜ多くの関数でDbContext
にこのデフォルトの自動変更検出を導入したのですか?確かではありませんが、それを無効にして適切なポイントでDetectChanges
を手動で呼び出すことは 高度であり、アプリケーションに微妙なバグを簡単に導入できるため、注意して[it]を使用できます =。
EF 4.3 CodeFirstを使用した小さな経験的テスト:
AutoDetectChanges = trueで1000オブジェクトを削除:23秒
AutoDetectChanges = false:11秒で1000個のオブジェクトを削除しました
AutoDetectChanges = trueで1000オブジェクトを挿入:21秒
AutoDetectChanges = falseで1000オブジェクトを挿入:13秒
.netcore 2.0では、これは次の場所に移動されました。
context.ChangeTracker.AutoDetectChangesEnabled = false;
あなたがここで見つけた答えに加えて。データベースレベルでは、追加するよりも挿入する方が作業が多いことを知っておくことが重要です。データベースは、新しいスペースを拡張/割り当てる必要があります。次に、少なくとも主キーインデックスを更新する必要があります。更新時にインデックスも更新される場合がありますが、あまり一般的ではありません。外部キーがある場合は、それらのインデックスも読み取って、参照整合性が維持されていることを確認する必要があります。トリガーも役割を果たすことができますが、それらは更新に同じように影響を与える可能性があります。
データベースのすべての作業は、ユーザーエントリによって発生する毎日の挿入アクティビティで意味があります。ただし、既存のデータベースをアップロードするだけの場合、または大量の挿入を生成するプロセスがある場合。あなたはそれを最後まで延期することによって、それをスピードアップする方法を見たいと思うかもしれません。通常、挿入中にインデックスを無効にすることが一般的な方法です。場合に応じて実行できる非常に複雑な最適化があり、それらは少し圧倒される場合があります。
一般的に、挿入は更新よりも時間がかかることを知っておいてください。