![](/img/trans.png)
[英]C# Low in memory and Insert into Oracle DB data - 1 million rows - OutOfMemory Exception
[英]Out of memory exception while moving CSV data (3 million data) into DataTable using c#
我有300万行和40列CSV文件。 我想使用SqlBulkCopy概念将CSV数据移入SQL Server。 为此,我使用CSV阅读器将每一列和每一行都移到了数据表中。 使用while循环在数据表中插入行时,出现内存异常。 注意:438184(以下样本的i值)记录已成功插入。 之后,我得到了内存异常。
SqlConnection con = new SqlConnection(connectionString);
con.Open();
SqlCommand SqlCmd = new SqlCommand();
SqlCmd.CommandTimeout = 0;
SqlCmd.Connection = con;
SqlTransaction transaction = con.BeginTransaction();
var fileStream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
StreamReader streamReader = new StreamReader(fileStream);
CsvReader reader = new CsvReader(streamReader);
DataTable table = new DataTable();
reader.ReadHeaderRecord();
foreach (var c in reader.HeaderRecord)
{
table.Columns.Add(c);
}
table.Rows.Clear();
int i = 0;
while (reader.HasMoreRecords)
{
DataRecord record = reader.ReadDataRecord();
table.Rows.Add(record[0], record[1], record[2], record[3], record[4], record[5], record[6], record[7], record[8], record[9], record[10], record[11], record[12], record[13], record[14], record[15], record[16], record[17], record[18], record[19], record[20], record[21], record[22], record[23], record[24], record[25], record[26], record[27], record[28], record[29], record[30], record[31], record[32], record[33], record[34], record[35], record[36], record[37], record[38], record[39]);
i++;
}
SqlBulkCopy copy = new SqlBulkCopy(con, SqlBulkCopyOptions.KeepIdentity, transaction);
copy.DestinationTableName = "SampleCSV";
copy.WriteToServer(table);
transaction.Commit();
con.Close();
谁能建议我如何解决这个问题?
您可以指定批量大小
查看SqlBulkCopy.BatchSize属性的更多详细信息
https://msdn.microsoft.com/zh-CN/library/system.data.sqlclient.sqlbulkcopy.batchsize(v=vs.110).aspx
或者,如果目标表模式是固定的,则可以使用SSIS包。
SqlBulkCopy copy = new SqlBulkCopy(con, SqlBulkCopyOptions.KeepIdentity, transaction);
//you can define any Banch of Data insert
copy.BatchSize(10000);
copy.DestinationTableName = "SampleCSV";
copy.WriteToServer(table);
transaction.Commit();
con.Close();
如果收到“内存异常”,则意味着您无法一次加载DataTable中的所有行。 您将需要在每X
行执行一次SqlBulkCopy并清除DataTable
然后再进行更多处理。
例如,以下代码将在DataTable
每加载100,000行执行一次SqlBulkCopy,然后在加载更多行之前清除所有行。
int i = 0;
while (reader.HasMoreRecords)
{
// INSERT rows every x
if(i % 100000 == 0)
{
ExecuteBulkCopy(conn, transaction, table);
table.Rows.Clear();
}
DataRecord record = reader.ReadDataRecord();
table.Rows.Add(record[0], record[1], record[2], record[3], record[4], record[5], record[6], record[7], record[8], record[9], record[10], record[11], record[12], record[13], record[14], record[15], record[16], record[17], record[18], record[19], record[20], record[21], record[22], record[23], record[24], record[25], record[26], record[27], record[28], record[29], record[30], record[31], record[32], record[33], record[34], record[35], record[36], record[37], record[38], record[39]);
i++;
}
// INSERT remaining row
if(table.Rows.Count > 0)
{
ExecuteBulkCopy(conn, transaction, table);
}
public void ExecuteBulkCopy(SqlConnection con, SqlTransaction transaction, DataTable table)
{
SqlBulkCopy copy = new SqlBulkCopy(con, SqlBulkCopyOptions.KeepIdentity, transaction);
copy.DestinationTableName = "SampleCSV";
copy.WriteToServer(table);
transaction.Commit();
}
编辑:回答子问题
如果使用批量插入或其他方式,可以减少此时间吗?
SqlBulkCopy
是最快的插入方法。 甚至我的库.NET Bulk Operations在后台也使用SqlBulkCopy。
300万个数据需要20分钟,这非常慢,但是根据您的表(char列,触发器,索引等),这也可能是正常的
这是要添加的两个对性能影响最大的配置。
例如5000与较小的批次相比,多次插入通常更快。
new SqlBulkCopy(connectionString, SqlBulkCopyOptions.TableLock))
通过锁定表,SqlBulkCopy将执行得更快。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.