我们在C#中使用SqlBulk Copy类。在sql中插入批量数据。我们有一张表,里面有1000万条记录。
我们在循环中以10,000的批量插入数据
我们正面临物理内存问题。内存增加并且不会减少。
以下是我们的代码。我们如何在使用sql批量复制时释放内存,或者是否有其他方法可以进行批量插入。
using (System.Data.SqlClient.SqlBulkCopy bulkCopy = new System.Data.SqlClient.SqlBulkCopy(SQlConn,SqlBulkCopyOptions.TableLock,null))
{
//bulkCopy = new System.Data.SqlClient.SqlBulkCopy(SQlConn);
bulkCopy.DestinationTableName = DestinationTable;
bulkCopy.BulkCopyTimeout = 0;
bulkCopy.BatchSize = dt1.Rows.Count;
Logger.Log("DATATABLE FINAL :" + dt1.Rows.Count.ToString(), Logger.LogType.Info);
if (SQlConn.State == ConnectionState.Closed || SQlConn.State == ConnectionState.Broken)
SQlConn.Open();
bulkCopy.WriteToServer(dt1); //DataTable
SQlConn.Close();
SQlConn.Dispose();
bulkCopy.Close();
if (bulkCopy != null)
{
((IDisposable)bulkCopy).Dispose();
}
}
这里更新完整的代码。
try
{
using (SqlConnection SQlConn = new SqlConnection(Common.SQLConnectionString))
{
DataTable dt1 = FillEmptyDateFields(dtDestination);
//SqlTableCreator ObjTbl = new SqlTableCreator(SQlConn);
//ObjTbl.DestinationTableName = DestinationTable;
using (System.Data.SqlClient.SqlBulkCopy bulkCopy = new System.Data.SqlClient.SqlBulkCopy(SQlConn,SqlBulkCopyOptions.TableLock,null))
{
//bulkCopy = new System.Data.SqlClient.SqlBulkCopy(SQlConn);
bulkCopy.DestinationTableName = DestinationTable;
bulkCopy.BulkCopyTimeout = 0;
bulkCopy.BatchSize = dt1.Rows.Count;
Logger.Log("DATATABLE FINAL :" + dt1.Rows.Count.ToString(), Logger.LogType.Info);
if (SQlConn.State == ConnectionState.Closed || SQlConn.State == ConnectionState.Broken)
SQlConn.Open();
bulkCopy.WriteToServer(dt1);
SQlConn.Close();
SQlConn.Dispose();
bulkCopy.Close();
if (bulkCopy != null)
{
((IDisposable)bulkCopy).Dispose();
}
}
}
dtDestination.Dispose();
System.GC.Collect();
dtDestination = null;
}
catch (Exception ex)
{
Logger.Log(ex, Logger.LogType.Error);
throw ex;
}
答案 0 :(得分:9)
这里的关键问题是:dt1
是什么,它来自哪里,你是如何发布它的?清除DataTable
实际上非常棘手,坦率地说,我通常不会在此推荐DataTable
来源。但是,如果必须使用DataTable
,请确保每次迭代使用完全独立的DataSet
/ DataTable
,然后释放旧的,以便可以回收
然而,更高效的是使用WriteToServer(IDataReader)
- 这允许您以流方式处理行。如果您在两个SQL系统之间进行复制,您甚至可以在单独的命令/连接上使用ExecuteReader()
,但IDataReader
非常简单,您可以为大多数源编写基本IDataReader
(或者找到这样做的库,例如CsvReader来处理分隔文件,例如csv / tsv)。
答案 1 :(得分:1)
我想问题就出在这一行:
bulkCopy.BatchSize = dt1.Rows.Count;
BatchSize属性确定在单个内部事务中插入的行数。这里的行大小可能是无限的。
http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlbulkcopy.batchsize.aspx
尝试将其设置为小而固定的数字应解决问题:
bulkCopy.BatchSize = 1000;
由您决定此处的最佳批量大小。