大量のデータを CSV (300 万行以上) からデータベースにロードする最も効率的な方法は何ですか。
- データをフォーマットする必要があります (たとえば、名前の列を姓と名に分割する必要があるなど)。
- 可能な限り効率的にこれを行う必要があります。つまり、時間の制約があります
C# アプリケーションを使用して行ごとにデータを読み取り、変換し、ロードするオプションを支持しますか? これは理想的ですか、そうでない場合、私のオプションは何ですか? マルチスレッドを使用する必要がありますか?
大量のデータを CSV (300 万行以上) からデータベースにロードする最も効率的な方法は何ですか。
C# アプリケーションを使用して行ごとにデータを読み取り、変換し、ロードするオプションを支持しますか? これは理想的ですか、そうでない場合、私のオプションは何ですか? マルチスレッドを使用する必要がありますか?
I/O バウンドになるため、マルチスレッド化によって必ずしも高速になるとは限りません。
前回これを行ったときは、約 12 行の C# でした。あるスレッドでは、プラッタからデータを読み取ることができるのと同じくらい速くハードディスクを実行しました。ソース ファイルから一度に 1 行ずつ読み取ります。
自分で書きたくない場合は、FileHelpersライブラリを試すことができます。Sébastien Lorion の作品もご覧ください。彼の CSV リーダーは、パフォーマンスの問題に対処するために特別に作成されています。
csvreaderを使用して、CSV をすばやく読み取ることができます。
SQL Server を使用していると仮定すると、csvreader をCachedCsvReader
使用してデータを DataTable に読み込み、これをSqlBulkCopyで使用して SQL Server にロードできます。
私はあなたの解決策に同意します。一度に 1 行ずつファイルを読み取ると、ファイル全体を一度にメモリに読み取るオーバーヘッドが回避されます。これにより、アプリケーションが迅速かつ効率的に実行され、主にファイルからの読み取り (比較的高速) と行の解析に時間がかかります。 . CSV に改行が埋め込まれていないか注意してください。使用している特定の CSV 形式が実際にデータ内の引用符の間に改行を出力するかどうかはわかりませんが、もちろん、このアルゴリズムを混乱させる可能性があります。
また、後続の外部キーに使用する必要がある生成されたキー値を取得する際に問題が発生しない場合は、データベースに送信する前に挿入ステートメントをバッチ処理することをお勧めします (1 つの文字列に多くの挿入ステートメントを含める)。生成されたキー値を取得する必要はありません)。SQL Server (それを使用している場合) はバッチごとに 2200 個のパラメーターしか処理できないため、それを考慮してバッチ サイズを制限してください。また、パラメーター化された TSQL ステートメントを使用して挿入を実行することをお勧めします。ファイルからレコードを読み取るよりも、レコードを挿入する方が時間がかかると思います。
どのデータベースを使用しているかは述べていませんが、言及した言語が C# であることを考えると、SQL Server を想定するつもりです。
BCP を使用してデータをインポートできない場合 (重要な処理が必要な場合はできないように思えます)、SSIS が次に速いオプションである可能性があります。世界で最も優れた開発プラットフォームではありませんが、非常に高速です。合理的な時間枠で自分で作成できるどのアプリケーションよりも確実に高速です。
BCP は非常に高速なので、データの読み込みに使用します。文字列操作の場合、データがそこにあれば、SQL で CLR 関数を使用します。このシナリオでは、複雑さが増してパフォーマンスが低下することを除いて、マルチスレッドは役に立ちません。
CSV ファイルの内容を 1 行ずつメモリ内の DataTable に読み込みます。DataTable にデータが入力されているときに、データを操作する (つまり、名と姓を分割する) ことができます。
CSV データがメモリに読み込まれたら、SqlBulkCopy を使用してデータをデータベースに送信します。
ドキュメントについては、http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlbulkcopy.writetoserver.aspxを参照してください。
本当に C# で実行したい場合は、DataTable を作成して入力し、ターゲット db テーブルを切り捨ててから、System.Data.SqlClient.SqlBulkCopy.WriteToServer(DataTable dt) を使用します。