データ量に負けない!C#でSQL Serverへの大量データ挿入を高速化するテクニック
C# で大量のデータを SQL Server に高速にバルク挿入する方法
SqlBulkCopy を使用したバルク挿入の利点
- 高速: 従来の INSERT ステートメントよりも大幅に高速なデータ転送速度を実現します。
- 効率的: データベースとの通信を最小限に抑え、サーバーリソースの負荷を軽減します。
- メモリ使用量が少ない: データをバッファリングせずに直接データベースに書き込むため、メモリ使用量を抑えられます。
SqlBulkCopy を使用したバルク挿入の手順
- 接続文字列を作成
string connectionString = "Data Source=localhost;Initial Catalog=TestDB;Integrated Security=True;";
- SqlBulkCopy インスタンスを作成
using (var sqlBulkCopy = new SqlBulkCopy(connectionString))
{
// 設定
}
- データソースを設定
データソースは、DataTable、DataReader、または IEnumerable<T> オブジェクトなど、さまざまな形式のデータソースを設定できます。
- 列マッピングを設定
データソースの列とターゲットテーブルの列をマッピングする必要があります。
- バルク挿入を実行
sqlBulkCopy.WriteToServer(dataTable);
パフォーマンスをさらに向上させるためのヒント
- データ型を一致させる: データソースとターゲットテーブルの列のデータ型を一致させると、変換処理が不要になり、パフォーマンスが向上します。
- バッチサイズを調整する: バッチサイズは、1 回の書き込み処理で送信されるデータの量を指定します。適切なバッチサイズは、データ量やネットワーク帯域幅によって異なります。
- バルク挿入エラー処理
バルク挿入処理中にエラーが発生する可能性があります。エラー処理を実装して、問題を特定し、解決する必要があります。
using (var connection = new SqlConnection("Data Source=localhost;Initial Catalog=TestDB;Integrated Security=True;"))
{
// データテーブルを作成
var dataTable = new DataTable();
dataTable.Columns.Add("Id", typeof(int));
dataTable.Columns.Add("Name", typeof(string));
// データを追加
for (int i = 0; i < 10000; i++)
{
dataTable.Rows.Add(i, $"Name{i}");
}
// SqlBulkCopy インスタンスを作成
using (var sqlBulkCopy = new SqlBulkCopy(connection))
{
sqlBulkCopy.DestinationTableName = "MyTable";
// 列マッピング
sqlBulkCopy.ColumnMappings.Add("Id", "Id");
sqlBulkCopy.ColumnMappings.Add("Name", "Name");
// バルク挿入を実行
sqlBulkCopy.WriteToServer(dataTable);
}
}
このコードは、10,000 行のデータを含む DataTable を "MyTable" テーブルにバルク挿入します。
その他のデータソース
DataReader を使用する場合
using (var connection = new SqlConnection("Data Source=localhost;Initial Catalog=TestDB;Integrated Security=True;"))
{
// DataReader を作成
var cmd = new SqlCommand("SELECT * FROM MySourceTable", connection);
var reader = cmd.ExecuteReader();
// SqlBulkCopy インスタンスを作成
using (var sqlBulkCopy = new SqlBulkCopy(connection))
{
sqlBulkCopy.DestinationTableName = "MyTable";
// 列マッピング
for (int i = 0; i < reader.FieldCount; i++)
{
sqlBulkCopy.ColumnMappings.Add(reader.GetName(i), reader.GetName(i));
}
// バルク挿入を実行
sqlBulkCopy.WriteToServer(reader);
}
}
IEnumerable<T> オブジェクトを使用する場合
using (var connection = new SqlConnection("Data Source=localhost;Initial Catalog=TestDB;Integrated Security=True;"))
{
// IEnumerable<T> オブジェクトを作成
var data = new List<MyObject>();
for (int i = 0; i < 10000; i++)
{
data.Add(new MyObject { Id = i, Name = $"Name{i}" });
}
// SqlBulkCopy インスタンスを作成
using (var sqlBulkCopy = new SqlBulkCopy(connection))
{
sqlBulkCopy.DestinationTableName = "MyTable";
// 列マッピング
sqlBulkCopy.ColumnMappings.Add("Id", "Id");
sqlBulkCopy.ColumnMappings.Add("Name", "Name");
// バルク挿入を実行
sqlBulkCopy.WriteToServer(data);
}
}
public class MyObject
{
public int Id { get; set; }
public string Name { get; set; }
}
これらのサンプルコードは、C# で大量のデータを SQL Server に高速にバルク挿入する方法を理解するのに役立つでしょう。
C# で大量のデータを SQL Server に挿入する他の方法
SqlBulkCopy.WriteToServer
メソッドの代わりに WriteToServerAsync
メソッドを使用すると、データをストリーミング挿入できます。これは、メモリ使用量をさらに削減したい場合に役立ちます。
Table-Valued Parameter (TVP)
TVP を使用すると、データをパラメータとしてストアドプロシージャに渡すことができます。これは、複雑なデータ挿入処理を行う場合に役立ちます。
データインポートウィザード
SQL Server Management Studio (SSMS) には、データインポートウィザードが用意されています。これは、GUI を使用してデータを簡単にインポートしたい場合に役立ちます。
ADO.NET Entity Framework
Entity Framework を使用すると、コードベースをよりシンプルに保ちながら、データベースとの CRUD 操作を行うことができます。
第三者製ライブラリ
FastMember や Dapper などの第三者製ライブラリを使用して、データ挿入処理をさらに高速化することができます。
最適な方法は、データ量、データソース、パフォーマンス要件などによって異なります。
一般的な目安
- 少量のデータの場合は、INSERT ステートメント で十分です。
- 大量のデータの場合は、SqlBulkCopy を使用するのが最善の方法です。
- 複雑なデータ挿入処理を行う場合は、TVP を検討してください。
- GUI を使用してデータをインポートしたい場合は、データインポートウィザード を使用してください。
- コードベースをよりシンプルに保ちたい場合は、Entity Framework を使用してください。
- データ挿入処理をさらに高速化したい場合は、第三者製ライブラリ を検討してください。
C# で大量のデータを SQL Server に挿入する方法はいくつかあります。それぞれの方法にはメリットとデメリットがあるので、要件に合わせて最適な方法を選択する必要があります。
c# sql sql-server