Sql批量复制内存问题
我们在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; }
这里的关键问题是:什么是dt1
,它来自哪里,你是如何发布它的? DataTable
实际上非常难以清理,坦率地说,我通常不会在这里推荐DataTable
源代码。 但是,如果必须使用DataTable
,则确保每次迭代使用完全独立的DataSet
/ DataTable
,并释放旧的DataSet
/ DataTable
以便可以回收。
但是,更高效的是使用WriteToServer(IDataReader)
– 这允许您以流方式处理行。 如果您在两个SQL系统之间进行复制,您甚至可以在单独的命令/连接上使用ExecuteReader()
,但IDataReader
非常简单,您可以为大多数源编写基本的IDataReader
(或者查找执行此操作的库,例如用于处理分隔文件(如csv / tsv)的CsvReader 。
我想这个问题出在这一行:
bulkCopy.BatchSize = dt1.Rows.Count;
BatchSize属性确定在单个内部事务中插入的行数。 这里的行大小可能是无限的。
http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlbulkcopy.batchsize.aspx
尝试将其设置为小而固定的数字应该解决问题:
bulkCopy.BatchSize = 1000;
由您决定此处的最佳批量大小。