Zenn
🚀

C# ADO.NETで大量データのINSERT処理をSqlBulkCopyで高速化

2025/02/05に公開

C#、ADO.NETで大量のデータをINSERTする処理を実装する場合、INSERTコマンドをループで発行すると処理時間が非常に長くなってしまう場合があります。
レコード件数が10~100程度であれば問題にならないかもしれませんが、例えば数万・数十万件になると、秒・分の単位ではなく数時間の処理が発生する可能性があります。

対応方法

このような場合、SQLBulkCopyを使用することで、大量のINSERT文を効率的に処理することができます。
数万件の場合でも秒の単位で処理を完了することが可能になります。(一般的な条件の場合)

using SqlBulkCopy bulkCopy = new SqlBulkCopy(connection))
{
    bulkCopy.DestinationTableName = "TargetTable";
    bulkCopy.BatchSize = 1000;
    bulkCopy.WriteToServer(sourceData);
}

SQLBulkCopyとは

SQLBulkCopyは、大量のデータを効率的にSQLServerに挿入するためのADO.NETの機能です。
通常のINSERT文と比較して、以下の利点があります:

  • トランザクションログの書き込みを最小限に抑制
  • ネットワークの往復回数を削減
  • メモリ使用量の最適化

実装例

using System;
using System.Data;
using System.Data.SqlClient;

public class BulkInsertExample
{
    private readonly string _connectionString;

    public BulkInsertExample(string connectionString)
    {
        _connectionString = connectionString;
    }

    public void PerformBulkInsert(DataTable sourceData)
    {
        // バッチサイズの設定(パフォーマンスチューニング用)
        const int batchSize = 1000;

        using (SqlConnection connection = new SqlConnection(_connectionString))
        {
            connection.Open();

            using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connection))
            {
                // 転送先のテーブル名を設定
                bulkCopy.DestinationTableName = "TargetTable";

                // カラムのマッピングを設定
                bulkCopy.ColumnMappings.Add("SourceColumn1", "TargetColumn1");
                bulkCopy.ColumnMappings.Add("SourceColumn2", "TargetColumn2");
                // 必要に応じて追加のマッピングを設定

                // バッチサイズの設定
                bulkCopy.BatchSize = batchSize;

                // タイムアウト設定(必要に応じて)
                bulkCopy.BulkCopyTimeout = 600; // 10分

                try
                {
                    // バルクコピーの実行
                    bulkCopy.WriteToServer(sourceData);
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"バルクインサート中にエラーが発生しました: {ex.Message}");
                    throw;
                }
            }
        }
    }

    // DataTableの作成例(テストデータ用)
    public DataTable CreateSampleDataTable()
    {
        DataTable dt = new DataTable();
        dt.Columns.Add("SourceColumn1", typeof(string));
        dt.Columns.Add("SourceColumn2", typeof(int));

        // テストデータの追加
        for (int i = 0; i < 10000; i++)
        {
            dt.Rows.Add($"Value{i}", i);
        }

        return dt;
    }
}

// 使用例
public class Program
{
    public static void Main()
    {
        string connectionString = "Your Connection String Here";
        var bulkInsert = new BulkInsertExample(connectionString);

        // サンプルデータの作成
        var sampleData = bulkInsert.CreateSampleDataTable();

        // バルクインサートの実行
        bulkInsert.PerformBulkInsert(sampleData);
    }
}

参考

上記の実装例は.NET Frameworkベースですが、.NETにも同様に適用することが可能です。

.NET Framework
https://learn.microsoft.com/ja-jp/dotnet/api/system.data.sqlclient.sqlbulkcopy?view=netframework-4.8.1

.NET
https://learn.microsoft.com/ja-jp/dotnet/api/system.data.sqlclient.sqlbulkcopy?view=net-9.0-pp&viewFallbackFrom=net-8.0

Discussion

ログインするとコメントできます