在处理大量数据时减少插入语句时间

时间:2013-06-03 09:35:39

标签: c# sql sql-server

我读到了SqlBulkCopy以及它可以减少插入大量行时使用的时间量的方式:我有一个excel文件希望我将它转换为dataTable然后我将此dataTable发送到存储过程(希望我无法更改其代码)将dataTable中的所有行插入数据库中的sql表

问题是我有10 000到5万行要插入是否有任何工作可以减少存储过程所花费的时间?

1 个答案:

答案 0 :(得分:2)

执行此操作的最佳方法是使用SqlBulkCopy将数据添加到临时表,然后将该数据提供给存储的proc。您需要编写一些SQL代码来进行处理,但这样做的性能优势应该是值得的。

如果您创建了一个新的存储过程,那么您可以在数据库引擎中运行所有这些代码,这样您就不会在应用程序和数据库引擎之间来回切换。

一些代码:

    var importData = new DataSet();
    xmlData.Position = 0;
    importData.ReadXml(xmlData);

    using (var connection = new SqlConnection(myConnectionString))
    {
      connection.Open();
      using (var trans = connection.BeginTransaction())
      {
        using (var sbc = new SqlBulkCopy(connection, SqlBulkCopyOptions.Default, trans) { DestinationTableName = myTableName })
        {
          foreach (DataColumn col in importData.Tables[0].Columns)
          {
            sbc.ColumnMappings.Add(col.ColumnName, col.ColumnName);
          }

          sbc.WriteToServer(importData.Tables[0]); //table 0 is the main table in this dataset

          // Now lets call the stored proc.
          var cmd = new SqlCommand("ProcessDataImport", connection)
              {
                CommandType = CommandType.StoredProcedure
              };
          cmd.CommandTimeout = 1200;
          cmd.ExecuteNonQuery();

          trans.Commit();
        }
        connection.Close();
        return null;
      }
    }

其中XmlData是一个流,其Xml数据与批量导入匹配,而myTableName包含要导入的表。记住,在进行批量复制时,列名必须匹配100%。案例也很重要。

proc看起来像这样:

CREATE PROCEDURE [ProcessDataImport]
AS
BEGIN
  DECLARE @IMPORTCOL INT

  WHILE EXISTS (SELECT X FROM TEMPTABLE)
  BEGIN
    SELECT @IMPORTCOL = (SELECT TOP 1 COLUMN1 FROM TEMPTABLE)
    EXEC DOTHEIMPORT @IMPORTCOL
    DELETE FROM TEMPTABLE WHERE COLUMN1 = @IMPORTCOL
  END
END