設定:
- 遅延読み込みが有効になっている Entity Framework 4 (モデル優先、階層ごとのテーブル)。
- テーブルの数は約 40 です (15 ~ 20 フィールドを超えるテーブルはありません)。
- SQL Server Express 2008 (r2 ではありません)。
- データベース トリガーやこのようなものは存在しません。ストレージにのみ使用されます。すべてのロジックはコードにあります。
- 現時点でのデータベース サイズは約 2 GB です。
- (主キーは Guid であり
Guid.NewGuid()
、これが重要な場合は - を介してコードで生成されます) - 複雑な操作結果 (複雑なオブジェクト グラフを生成する) を保存するには、40 秒から 60 秒かかります (返される数
SaveChanges
は約 8000 で、ほとんどが追加されたオブジェクトで、一部が変更されています)。 - 空の (またはほぼ空の) データベースで同じ操作結果を保存するには、通常、同じコンピューターで約 1 秒かかります。
この問題に影響を与えると思われる唯一の変数は、データベースのサイズです。ただし、私は呼び出しを測定しているだけであることに注意してくださいContext.SaveChages()
(したがって、この問題に影響を与えない奇妙なクエリがどこかにある場合でも)。
この操作がこれほど長く続く理由についての提案は大歓迎です。
更新 1
明確にするために-実行に40〜60秒かかるコードは次のとおりです(DBサイズが約2GBの場合にのみこれほど長くかかります):
Stopwatch sw = Stopwatch.StartNew();
int count = objectContext.SaveChanges(); // this method is not overridden
Debug.Write(sw.ElapsedMilliseconds); // prints out 40000 - 60000 ms
Debug.Write(count); // I am testing with exactly the same operation and the
// result always gives the same count for it (8460)
空の DB での同じ操作には、約 1000 ミリ秒かかります (それでも同じカウント - 8460 が得られます)。したがって、問題は、データベースのサイズがどのように影響するSaveChanges()
かということです。
更新 2
パフォーマンス プロファイラーを実行すると、(「コードの観点から」) 主なボトルネックは次の方法であることがわかります。
Method: static SNINativeMethodWrapper.SNIReadSync
Called: 3251 times
Avg: 10.56 ms
Max: 264.25 ms
Min: 0.01 ms
Total: 34338.51 ms
アップデート 3
データベース内のすべての PK と FK に対して非クラスター化インデックスがあります。ランダムな Guid を代理キー (シーケンシャルではなく) として使用しているため、断片化は常に非常に高いレベルにあります。すべての DB インデックスを再構築した直後に問題の操作を実行してテストを試みましたが (断片化はすべてのインデックスで 2 ~ 3% 未満でした)、状況がまったく改善されなかったようです。
さらに、問題の操作中、プロセスに関与する 1 つのテーブルには約 400 万行が含まれていると言わざるを得ません (このテーブルには多くの挿入が行われます)。SQL プロファイラーは、そのテーブルへの挿入が 1 から 200 ミリ秒続く可能性があることを示しています (これは「スパイク」です)。繰り返しますが、インデックスが新たに再構築された場合、これは変化しないようです。
いずれにせよ、(現時点では) 問題はアプリケーションの SQL Server 側にあるようです。なぜなら、時間のかかる主なものはそのSNIReadSync
メソッドだからです。私が完全に無知である場合は修正してください。