タブ区切りのテキストファイルがあります。ファイルは約100MBです。このファイルのデータを SQL サーバー テーブルに保存したいと考えています。このファイルには、SQL Server に保存されたときに 100 万件のレコードが含まれます。これを達成するための最良の方法は何ですか?
C# で momory データテーブルを作成し、それを SQL サーバーにアップロードできますが、この場合、100 MB のファイル全体がメモリに読み込まれます。ファイルサイズが大きくなったら?
タブ区切りのテキストファイルがあります。ファイルは約100MBです。このファイルのデータを SQL サーバー テーブルに保存したいと考えています。このファイルには、SQL Server に保存されたときに 100 万件のレコードが含まれます。これを達成するための最良の方法は何ですか?
C# で momory データテーブルを作成し、それを SQL サーバーにアップロードできますが、この場合、100 MB のファイル全体がメモリに読み込まれます。ファイルサイズが大きくなったら?
問題ない; CsvReader
ほとんどの区切りテキスト形式を処理し、 を実装するIDataReader
ため、 をフィードするために使用できますSqlBulkCopy
。例えば:
using (var file = new StreamReader(path))
using (var csv = new CsvReader(file, true)) // true = first row is headers
using (var bcp = new SqlBulkCopy(connectionString))
{
bcp.DestinationTableName = "Foo";
bcp.WriteToServer(csv);
}
CsvReader
多くのオプションがあり、より微妙なファイル処理 (区切り記号の規則の指定など) があることに注意してください。SqlBulkCopy
は高性能な一括読み込み API で、非常に効率的です。これはストリーミング リーダー/ライター API です。一度にすべてのデータをメモリにロードするわけではありません。
ファイルを行ごとに読み取る必要があるため、行全体をメモリにロードする必要はありません。
using (var file = System.IO.File.OpenText(filename))
{
while (!file.EndOfStream)
{
string line = file.ReadLine();
// TODO: Do your INSERT here
}
}
* アップデート *
"これにより、SQL Server に対して 100 万個の個別の挿入コマンドが作成されます。まとめて作成する方法はありますか"
パラメータ化されたクエリを使用することもできますが、これは 1M の挿入を発行しますが、それでも非常に高速です。
または、 を使用することもできますがSqlBulkCopy
、サードパーティのライブラリを使用したくない場合は、かなり困難になります。MS ライセンスに慣れている場合は、拡張メソッドを提供するLINQ Entity Data Reader (Ms-PL ライセンスで配布) を使用できます。AsDataReader
void MyInsertMethod()
{
using (var bulk = new SqlBulkCopy("MyConnectionString"))
{
bulk.DestinationTableName = "MyTableName";
bulk.WriteToServer(GetRows().AsDataReader());
}
}
class MyType
{
public string A { get; set; }
public string B { get; set; }
}
IEnumerable<MyType> GetRows()
{
using (var file = System.IO.File.OpenText("MyTextFile"))
{
while (!file.EndOfStream)
{
var splitLine = file.ReadLine().Split(',');
yield return new MyType() { A = splitLine[0], B = splitLine[1] };
}
}
}
MS ライセンス コードも使用したくない場合は、IDataReader
自分で実装することもできますが、それは PITA になります。上記の CSV 処理 ( Split(',')
) はまったく堅牢ではないことに注意してください。また、表の列名は のプロパティ名と同じでなければならないことに注意してくださいMyType
。TBH、これに関するマークの回答を使用することをお勧めします