オンライン・バッチ処理高速化 測定
Dapperを使って10万件のデータの追加・更新・削除を比べてみました。
結果は以下の通りでBulkCopyが1/10から1/20倍高速になっています。
意外なのがDapperのListを渡した更新処理が思った以上に速い点です。
10万件をループして更新すると測定するのが大変なくらい遅くなるのですが、MiniProfilerで発行されているSQLを見ると10万回実行されているにもかかわらずストアドの2から4倍程度で処理できてきます。
処理 | 時間(秒) |
---|---|
Dapperで10万件のListのINSERT文の実行 | 38.10 |
ストアドでINSERT文の実行 10万件 | 11.79 |
BulkCopy 10万件 | 0.55 |
Dapperで10万件のListのUPDATE文の実行 10万件 | 37.87 |
ストアドでカーソルを利用したUPDATE文の実行 10万件 | 17.81 |
BulkCopyで一時テーブルに10万件出力後、一時テーブルを利用したUPDATE文 | 0.74 |
Dapperで10万件のListのDELETE文の実行 | 37.96 |
ストアドでカーソルを利用したDELETE文の実行 10万件 | 17.38 |
BulkCopyで一時テーブルに10万件出力後、一時テーブルを利用したDELETE文 | 1.36 |
参考までにUPDATE処理のプログラムを載せておきます
Dapperで10万件のListのUPDATE文実行
var list = connection.Query("SELECT * FROM TestTable"); connection.Execute("UPDATE TestTable SET Value = @Value WHERE Id = @Id", list);
ストアドでカーソルを利用したUPDATE文の実行 10万件
Create PROCEDURE dbo.UpdateData AS DECLARE @Val nvarchar(50) DECLARE @Id int DECLARE TestCur cursor FOR SELECT Id,[Value] FROM TestTable OPEN TestCur FETCH NEXT FROM TestCur INTO @Id,@Val WHILE (@@fetch_status = 0) BEGIN UPDATE TestTable SET TestTable.Value = @val WHERE CURRENT OF TestCur; FETCH NEXT FROM TestCur INTO @Id,@Val end CLOSE TestCur DEALLOCATE TestCur RETURN
BulkCopyで一時テーブルに10万件出力後、一時テーブルを利用したUPDATE文
connection.Execute("SELECT * INTO #Temp FROM TestTable WHERE 1=0"); using (SqlBulkCopy bulkCopy = new SqlBulkCopy(baseConnection)) { bulkCopy.DestinationTableName = "#Temp"; bulkCopy.WriteToServer( connection.Query("SELECT * FROM TestTable") .Select(x => new { id = x.Id, value = x.Value }) .ToDataReader() ); } connection.Execute("UPDATE TestTable SET TestTable.Value = #Temp.Value FROM TestTable INNER JOIN #Temp ON TestTable.Id = #Temp.Id");
MiniProfilerの結果
3.3ms SELECT * INTO #Temp FROM TestTable WHERE 1=0 250.2ms for 2 query duplicates SELECT * FROM TestTable 458ms UPDATE TestTable SET TestTable.Value = #Temp.Value FROM TestTable INNER JOIN #Temp ON TestTable.Id = #Temp.Id 18147.5ms UpdateData3 32383.7ms for 100000 query duplicates UPDATE TestTable SET Value = @Value WHERE Id = @Id
今回のテストはノートPCでDBとアプリが同じPCなので実際の環境とは異なりますが、参考にはなると思います。