Sql批量复制内存问题

时间:2012-10-10 12:16:58

标签: c# sql sql-server

我们在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;

        }

2 个答案:

答案 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;

由您决定此处的最佳批量大小。