【C#+DB】EntityFramework は遅い?性能問題改善点

※本ページはサイドバーまたは本文内にアフィリエイト広告を利用しています

業務でサーバサイドやバッチ系アプリを作成する際に重要なのがパフォーマンス。最初はテストを通すために3~5件程度をテストデータで準備するので留意しないのですが、結合テスト以降に本番データを投入する時に言われてしまう「遅い」「1日流し続けても終わらない」

今回サーバサイドを作る上で実際に動作の遅さを目の当たりにしてしまったので、どう対応したかをメモの意味も含めて残しておきたいと思います。

ToList ではなくToArrayを使う

これは劇的な改善にはなりませんでしたが、ToListよりもToArrayを使った方が性能が良いです。

ToList と ToArray のどちらを使うべきか

注意点としてはDBの結果をループで回す時に終了条件を件数で回す時はListと配列では定義がちょっと違うのですがそこだけ気をつければどちらでも今後の処理に対応できたりします。

EntityFrameWork拡張ツールをインストールしてBulkInsertを用いる

この EntityFrameWork Coreの拡張ツールとしてZ.EntityFramework.Extensions.EFCoreがありますが、これを使用すればDBの保存形式にBulkInsertが使用できます。参考にしたのは下記の記事です。→ 2022/2/10確認したらリンク先が消滅していました

SQL Bulk Insertオペレーション – Entity FrameworkのBulkInsertよりずっと速くする方法

これも試したのですが、単体のテーブルの登録には良さそうですが、SaveChanges()で子テーブルの挿入も実現したい場合は子テーブルの登録ができませんでした

リンク先のサイトはEntityFrameworkやZ.EntityFramework.Extensions.EFCore を使うよりもSqlBulkCopyを使った方が早かったですよ。という内容でした。

1対多のテーブルで多のデータをコピーや移行する時はループで回したりNew List<xxxxxx>をするよりSelect+Fromでコピーさせる

こちらはDB間でデータの移行したり、複製したりする時にパフォーマンスを改善する手段です。通常複数のデータを複製したりするときは下記のようにnewし直したり中のFK等のデータだけ変えたい時にループで回して設定したりするのが通常ですが、Select+Fromを使って使う側はコードも実際の処理時間も若干短縮させることができます。

下記ソースは実際の環境で打ったものではなく、説明のためにイメージで打っていますのであらかじめご了承ください。(構文ミス・スペルミスありそう)

修正前

IQueryable copymoto = dbcontext.entity().AsNoTracking;

1.
var copysaki = new List<Entity>(copymoto);

2.
List<Entity> copysaki = new List<Entity>();

foreach(var item in copymoto)
{
     copy = new Entity()
     {
          id = guid(),
          Attribute = item.Attribute,
          省略 
     };

     copysaki.Add(copy);
}

修正後

IQueryable copymoto = dbcontext.entity().AsNoTracking;

var copysaki = copymoto.select( x => From(copymoto));

省略
}

// 別のメソッド
private Entity From(Entitycopymoto)
{
    id = guid(),
    Attribute = copymoto.Attribute,
    省略

}

Parallel.For/ Parallel.Foreachを使い、ループ処理そのものを並列化する

こちらは例えばリード後の大量データをファイルに出力したりするときに使います。とはいえ、並列処理ということでソートをきちんとして出したい時にはもしかしたら使用できないかもしれません。こちらについては以下のリンクにとても詳しく書かれているので参照してみてください。

(C#)Parallel.For, Parallel.ForEach並列処理の挙動確認

このParallelを使用したループできるのはあくまで出力/表示時に有効でDB書き込みに使おうとするとエラーになってしまいましたので用途限定なのが残念です。

【110円】この続きは特に性能改善効果が高い情報です
気に入ったらシェアお願いします!

【イナコーシステムからのお知らせ】

読者様への返礼特典付き投げ銭サービス

金額に応じて特典の実用性がUP!

  • ○あなたの名前を半永久的に残せる!
  • ○あなたのブログ/動画チャンネル紹介記事を執筆・サイドバーのリンクエリアに掲載!
  • ○あなたの悩み(エンジニア、ブログなど)を通話付きでアドバイス/サポート。回数制限なし!