C#でデータベースに行を追加するパフォーマンスを測定してみた
最近コンソールアプリで C# から SQLServer にデータのバッチ投入・更新・削除を試しています。単純な SQL の実行はいつも Dapper を利用しているのですが思うような実行結果にならなかったため、何種類かの方法でデータの一括投入のパフォーマンス計測してみました。
測定方法
今回は .NET Core 3.1 で作った簡単なプログラムを Azure Functions 上で実行し、データ挿入のパフォーマンスを測定します。
測定対象は Dapper 、 EntityFramework Core 、および SqlBulkCopy です。適当なデータを千件、1万件一括挿入してみます。それぞれ10回実行し、最初の1回を除いた9回の平均値を取ります。
環境
- Runtime/Libs
- Azure Resources (West US 2)
- Azure Functions (.NET Core 3.1 / AppService Plan S1)
- Azure SQL Database (S3 / DTU 100)
結果
一括挿入するなら BulkCopy 一択です。超高速で他を寄せ付けません。
Dapper は BulkInsert 機能がデフォルトでは存在せず、件数分の INSERT を実行します。つらい。
EFCore はデフォルトだと500件?を一括挿入するためパフォーマンスは良い、、、と見せかけ、オブジェクト管理に関する処理が重すぎて結局 Dapper に近い時間かかります。もっとも、今回は一括で SaveChanges を呼び出していますので分割すればもう少しパフォーマンスの向上は狙えるかもしれません。
以下、測定結果。
種類 | 回数 | 平均 | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
Dapper | 1000 | 918 | 1345 | 949 | 975 | 933 | 848 | 896 | 910 | 915 | 901 | 939 |
EFCore | 1000 | 751 | 2867 | 796 | 752 | 781 | 730 | 726 | 748 | 735 | 734 | 759 |
BulkCopy | 1000 | 21 | 312 | 21 | 21 | 25 | 20 | 22 | 21 | 21 | 17 | 22 |
Dapper | 10000 | 8273 | 10003 | 9196 | 8076 | 7975 | 7976 | 7819 | 8099 | 9436 | 8033 | 7844 |
EFCore | 10000 | 7588 | 9715 | 7994 | 7525 | 7430 | 7618 | 7593 | 7558 | 7598 | 7502 | 7473 |
BulkCopy | 10000 | 387 | 136 | 373 | 626 | 354 | 346 | 357 | 364 | 361 | 361 | 340 |