テキスト ファイルから約 200 万行を挿入する必要があります。
挿入すると、いくつかのマスターテーブルを作成する必要があります。
このような大量のデータ セットを SQL Server に挿入するための最善かつ迅速な方法は何ですか?
テキスト ファイルから約 200 万行を挿入する必要があります。
挿入すると、いくつかのマスターテーブルを作成する必要があります。
このような大量のデータ セットを SQL Server に挿入するための最善かつ迅速な方法は何ですか?
DataSetでテキストファイルのデータを読んだほうがいいと思います
SqlBulkCopyを試す - C# アプリから SQL に一括挿入
// connect to SQL
using (SqlConnection connection = new SqlConnection(connString))
{
// make sure to enable triggers
// more on triggers in next post
SqlBulkCopy bulkCopy = new SqlBulkCopy(
connection,
SqlBulkCopyOptions.TableLock |
SqlBulkCopyOptions.FireTriggers |
SqlBulkCopyOptions.UseInternalTransaction,
null
);
// set the destination table name
bulkCopy.DestinationTableName = this.tableName;
connection.Open();
// write the data in the "dataTable"
bulkCopy.WriteToServer(dataTable);
connection.Close();
}
// reset
this.dataTable.Clear();
また
上部のステップ1を実行した後
詳細については、この記事を確認できます: C# DataTable と SQL サーバーの OpenXML 関数を使用したデータの一括挿入
ただし、200 万レコードでテストされていません。200 万レコードをロードして挿入する必要があるため、マシンのメモリを消費します。
SqlBulkCopy の解決策を次に示します。
StreamReader を使用して、テキスト ファイルの変換と処理を行いました。結果は私のオブジェクトのリストでした。
Datatable
orList<T>
と Buffer size ( )を取るよりもクラスを作成しましたCommitBatchSize
。拡張機能を使用してリストをデータ テーブルに変換します (2 番目のクラス)。
非常に高速に動作します。私の PC では、10 秒以内に 1000 万を超える複雑なレコードを挿入できます。
クラスは次のとおりです。
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DAL
{
public class BulkUploadToSql<T>
{
public IList<T> InternalStore { get; set; }
public string TableName { get; set; }
public int CommitBatchSize { get; set; }=1000;
public string ConnectionString { get; set; }
public void Commit()
{
if (InternalStore.Count>0)
{
DataTable dt;
int numberOfPages = (InternalStore.Count / CommitBatchSize) + (InternalStore.Count % CommitBatchSize == 0 ? 0 : 1);
for (int pageIndex = 0; pageIndex < numberOfPages; pageIndex++)
{
dt= InternalStore.Skip(pageIndex * CommitBatchSize).Take(CommitBatchSize).ToDataTable();
BulkInsert(dt);
}
}
}
public void BulkInsert(DataTable dt)
{
using (SqlConnection connection = new SqlConnection(ConnectionString))
{
// make sure to enable triggers
// more on triggers in next post
SqlBulkCopy bulkCopy =
new SqlBulkCopy
(
connection,
SqlBulkCopyOptions.TableLock |
SqlBulkCopyOptions.FireTriggers |
SqlBulkCopyOptions.UseInternalTransaction,
null
);
// set the destination table name
bulkCopy.DestinationTableName = TableName;
connection.Open();
// write the data in the "dataTable"
bulkCopy.WriteToServer(dt);
connection.Close();
}
// reset
//this.dataTable.Clear();
}
}
public static class BulkUploadToSqlHelper
{
public static DataTable ToDataTable<T>(this IEnumerable<T> data)
{
PropertyDescriptorCollection properties =
TypeDescriptor.GetProperties(typeof(T));
DataTable table = new DataTable();
foreach (PropertyDescriptor prop in properties)
table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);
foreach (T item in data)
{
DataRow row = table.NewRow();
foreach (PropertyDescriptor prop in properties)
row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;
table.Rows.Add(row);
}
return table;
}
}
}
List<PuckDetection>
カスタム オブジェクト( ListDetections
)のリストを挿入する場合の例を次に示します。
var objBulk = new BulkUploadToSql<PuckDetection>()
{
InternalStore = ListDetections,
TableName= "PuckDetections",
CommitBatchSize=1000,
ConnectionString="ENTER YOU CONNECTION STRING"
};
objBulk.Commit();
必要に応じて、BulkInsert
クラスを変更して列マッピングを追加できます。例では、最初の列として ID キーがあります (これは、データテーブルの列名がデータベースと同じであると仮定しています)
//ADD COLUMN MAPPING
foreach (DataColumn col in dt.Columns)
{
bulkCopy.ColumnMappings.Add(col.ColumnName, col.ColumnName);
}
bcp ユーティリティを使用します。(一括コピー プログラム) 毎月約 150 万のテキスト レコードを読み込みます。各テキスト レコードは 800 文字幅です。私のサーバーでは、150 万のテキスト レコードを SQL Server テーブルに追加するのに約 30 秒かかります。
bcp の手順は、http://msdn.microsoft.com/en-us/library/ms162802.aspxにあります。
私は最近このシナリオに遭遇し(700万行をはるかに超えています)、一度に5,000のセグメントで(生データをSQL挿入ステートメントに解析した後)powershell経由でsqlcmdを使用しました(SQLは1つの一括ジョブで700万行を処理できません) SQL Server 2012 Enterprise の新しいシーケンス コマンドを活用する必要があったため、5K の小さな断片に分割しない限り、500,000 行にもなります。上記のシーケンス コマンドを使用して、700 万行のデータをすばやく効率的に挿入するプログラム的な方法を見つけることができませんでした。
第 2 に、一度に 100 万行以上のデータを挿入する場合に注意すべきことの 1 つは、挿入プロセス中の CPU とメモリ (主にメモリ) の消費です。SQL は、上記のプロセスを解放せずに、この規模のジョブでメモリ/CPU を消費します。言うまでもなく、サーバーに十分な処理能力やメモリがない場合、短時間で非常に簡単にクラッシュする可能性があります (これは難しい方法であることがわかりました)。メモリ消費量が 70 ~ 75% を超えた場合は、サーバーを再起動するだけで、プロセスが解放されて通常の状態に戻ります。
実際に最終的な実行計画を立てる前に、試行錯誤のテストを何度も実行して、サーバーの制限を確認する必要がありました (使用できる CPU/メモリ リソースが限られている場合)。これを本番環境に展開する前に、テスト環境で同じことを行うことをお勧めします。