sql-server-2005 - 如何将慢速参数化插入更改为快速批量复制(甚至从内存中)

标签 sql-server-2005 insert copy performance bulk

我的代码中有这样的东西(.Net 2.0,MS SQL)

SqlConnection connection = new SqlConnection(@"Data Source=localhost;Initial
Catalog=DataBase;Integrated Security=True");
  connection.Open();

  SqlCommand cmdInsert = connection.CreateCommand();
  SqlTransaction sqlTran = connection.BeginTransaction();
  cmdInsert.Transaction = sqlTran;

  cmdInsert.CommandText =
     @"INSERT INTO MyDestinationTable" +
      "(Year, Month, Day, Hour,  ...) " +
      "VALUES " +
      "(@Year, @Month, @Day, @Hour, ...) ";

  cmdInsert.Parameters.Add("@Year", SqlDbType.SmallInt);
  cmdInsert.Parameters.Add("@Month", SqlDbType.TinyInt);
  cmdInsert.Parameters.Add("@Day", SqlDbType.TinyInt);
  // more fields here
  cmdInsert.Prepare();

  Stream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read);

  StreamReader reader = new StreamReader(stream);
  char[] delimeter = new char[] {' '};
  String[] records;
  while (!reader.EndOfStream)
  {
    records = reader.ReadLine().Split(delimeter, StringSplitOptions.None);

    cmdInsert.Parameters["@Year"].Value = Int32.Parse(records[0].Substring(0, 4));
    cmdInsert.Parameters["@Month"].Value = Int32.Parse(records[0].Substring(5, 2));
    cmdInsert.Parameters["@Day"].Value = Int32.Parse(records[0].Substring(8, 2));
    // more here complicated stuff here
    cmdInsert.ExecuteNonQuery()
  }
  sqlTran.Commit();
  connection.Close();

将 cmdInsert.ExecuteNonQuery() 注释掉后,这段代码的执行时间不到 2 秒。 SQL 执行需要 1m 20 秒。大约有 50 万条记录。表之前被清空。类似功能的 SSIS 数据流任务大约需要 20 秒。
  • 批量插入 不是一个选项(见下文)。我在这个导入过程中做了一些花哨的东西。
  • 我的测试机器是 Core 2 Duo 和 2 GB RAM。
  • 在任务管理器中查看时,CPU 尚未完全化。 IO 似乎也没有被充分利用。
  • Schema 非常简单:一张表以 AutoInt 作为主索引,并且少于 10 个整数、小整数和字符 (10)。

  • 经过这里的一些回答后,我发现可以执行 从内存中批量复制 !我拒绝使用批量复制,因为我认为它必须从文件中完成...

    现在我使用它,它需要大约 20 秒(如 SSIS 任务)
      DataTable dataTable = new DataTable();
    
      dataTable.Columns.Add(new DataColumn("ixMyIndex", System.Type.GetType("System.Int32")));   
      dataTable.Columns.Add(new DataColumn("Year", System.Type.GetType("System.Int32")));   
      dataTable.Columns.Add(new DataColumn("Month", System.Type.GetType("System.Int32")));
      dataTable.Columns.Add(new DataColumn("Day", System.Type.GetType("System.Int32")));
     // ... and more to go
    
      DataRow dataRow;
      object[] objectRow = new object[dataTable.Columns.Count];
    
      Stream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read);
    
      StreamReader reader = new StreamReader(stream);
      char[] delimeter = new char[] { ' ' };
      String[] records;
      int recordCount = 0;
      while (!reader.EndOfStream)
      {
        records = reader.ReadLine().Split(delimeter, StringSplitOptions.None);
    
        dataRow = dataTable.NewRow();
        objectRow[0] = null; 
        objectRow[1] = Int32.Parse(records[0].Substring(0, 4));
        objectRow[2] = Int32.Parse(records[0].Substring(5, 2));
        objectRow[3] = Int32.Parse(records[0].Substring(8, 2));
        // my fancy stuf goes here
    
        dataRow.ItemArray = objectRow;         
        dataTable.Rows.Add(dataRow);
    
        recordCount++;
      }
    
      SqlBulkCopy bulkTask = new SqlBulkCopy(connection, SqlBulkCopyOptions.TableLock, null);
      bulkTask.DestinationTableName = "MyDestinationTable"; 
      bulkTask.BatchSize = dataTable.Rows.Count;
      bulkTask.WriteToServer(dataTable);
      bulkTask.Close();
    

    最佳答案

    不要单独插入每条记录,而是尝试使用 SqlBulkCopy类一次批量插入所有记录。

    创建一个数据表并将所有记录添加到数据表中,然后使用 SqlBulkCopy . WriteToServer一次批量插入所有数据。

    关于sql-server-2005 - 如何将慢速参数化插入更改为快速批量复制(甚至从内存中),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/127152/

    相关文章:

    php - 在循环中插入 sql 查询是好事还是坏事?

    python - 在mysql python中插入多个插入的csv文件

    java - 如何将jar内的文件复制到jar外?

    sql - 如何在 SQL Server 中创建 rownum

    sql-server - SQL Server 2005 中的临时表不会自动删除

    sql - 如何清除 Sql Server 2005 中的连接

    c# - 使用比较函数对插入进行排序

    c - C语言如何将图片复制到目录

    c# - 使用投影时,IEnumerable 和 Lists 之间有什么区别?

    sql-server - SQL Server Management Studio - 在表列表中使用多个过滤器?