4

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

        }
4

2 回答 2

9

这里的关键问题是:什么是dt1,它来自哪里,以及你是如何发布它的?DataTable实际上清理起来非常棘手,坦率地说,我通常不会DataTable在这里推荐一个来源。但是,如果您必须使用DataTable,请确保并使用完全独立的DataSet/DataTable每次迭代,并释放旧的,以便它可以回收。

然而,更有效的是使用WriteToServer(IDataReader)- 这允许您以流方式处理行。如果您在两个 SQL 系统之间进行复制,您甚至可以只ExecuteReader()在单独的命令/连接上使用,但这IDataReader非常简单,您可以IDataReader为大多数源编写一个基本的(或找到这样做的库,例如用于处理分隔文件的CsvReader例如 csv/tsv)。

于 2012-10-10T12:24:28.140 回答
1

我想问题出在这一行:

bulkCopy.BatchSize = dt1.Rows.Count; 

BatchSize 属性确定在单个内部事务中插入多少行。这里的行大小可能是无限的。

http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlbulkcopy.batchsize.aspx

尝试将其设置为一个小而固定的数字应该可以解决问题:

bulkCopy.BatchSize = 1000;

在这里决定最佳批量大小由您决定。

于 2012-10-10T12:27:45.853 回答