加速sql INSERT

时间:2010-05-31 17:15:23

标签: sql-server-2008

我有以下方法将数百万行数据插入表中(我使用SQL 2008),它似乎很慢,有没有办法加速INSERT?

以下是代码段 - 我使用MS企业库

        public void InsertHistoricData(List<DataRow> dataRowList)
        {
            string sql = string.Format( @"INSERT INTO [MyTable] ([Date],[Open],[High],[Low],[Close],[Volumn])
                VALUES( @DateVal, @OpenVal, @High, @Low, @CloseVal, @Volumn )");

            DbCommand dbCommand = VictoriaDB.GetSqlStringCommand( sql );
            DB.AddInParameter(dbCommand, "DateVal", DbType.Date);
            DB.AddInParameter(dbCommand, "OpenVal", DbType.Currency);
            DB.AddInParameter(dbCommand, "High", DbType.Currency );
            DB.AddInParameter(dbCommand, "Low", DbType.Currency);
            DB.AddInParameter(dbCommand, "CloseVal", DbType.Currency);
            DB.AddInParameter(dbCommand, "Volumn", DbType.Int32);

            foreach (NasdaqHistoricDataRow dataRow in dataRowList)
            {
                DB.SetParameterValue( dbCommand, "DateVal", dataRow.Date );
                DB.SetParameterValue( dbCommand, "OpenVal", dataRow.Open );
                DB.SetParameterValue( dbCommand, "High", dataRow.High );
                DB.SetParameterValue( dbCommand, "Low", dataRow.Low );
                DB.SetParameterValue( dbCommand, "CloseVal", dataRow.Close );
                DB.SetParameterValue( dbCommand, "Volumn", dataRow.Volumn );

                DB.ExecuteNonQuery( dbCommand );
            }
        }

4 个答案:

答案 0 :(得分:10)

请考虑使用bulk insert

  

SqlBulkCopy可让您高效批量处理   使用来自的数据加载SQL Server表   另一个来源。 SqlBulkCopy类   可用于仅将数据写入SQL   服务器表。但是,数据   源不仅限于SQL Server;   任何数据源都可以使用   因为数据可以加载到   DataTable实例或用。读取   IDataReader实例。对于这个例子   该文件将包含大约1000   记录,但这段代码可以处理   大量数据。

此示例首先创建DataTable并使用数据填充它。这保存在记忆中。

DataTable dt = new DataTable();
string line = null;
bool firstRow = true;

using (StreamReader sr = File.OpenText(@"c:\temp\table1.csv"))
{  
      while ((line = sr.ReadLine()) != null)
      {
            string[] data = line.Split(',');
            if (data.Length > 0)
            {
                  if (firstRow)
                  {
                        foreach (var item in data)
                        {
                              dt.Columns.Add(new DataColumn());
                        }
                        firstRow = false;
                   }

                   DataRow row = dt.NewRow();
                   row.ItemArray = data;
                   dt.Rows.Add(row);
             }
      }
}

然后我们一次将DataTable推送到服务器。

using (SqlConnection cn = new SqlConnection(ConfigurationManager.ConnectionStrings["ConsoleApplication3.Properties.Settings.daasConnectionString"].ConnectionString))
{
      cn.Open();
      using (SqlBulkCopy copy = new SqlBulkCopy(cn))
      {
            copy.ColumnMappings.Add(0, 0);
            copy.ColumnMappings.Add(1, 1);
            copy.ColumnMappings.Add(2, 2);
            copy.ColumnMappings.Add(3, 3);
            copy.ColumnMappings.Add(4, 4);
            copy.DestinationTableName = "Censis";
            copy.WriteToServer(dt);
      }
} 

答案 1 :(得分:1)

在执行大量插入或任何数据更改时,任何关系数据库的一个常规提示是首先删除所有二级索引,然后再重新创建它们。

为什么这样做?对于二级索引,索引数据将位于磁盘上的其他位置,而不是数据,因此每个索引写入表的每个记录最多只能进行额外的读/写更新。事实上,它可能比这更糟糕,因为数据库有时会决定它需要对索引进行更严肃的重组操作。

在插入运行结束时重新创建索引时,数据库将只执行一次全表扫描以读取和处理数据。您不仅最终在磁盘上获得了更好的组织索引,而且所需的工作总量将更少。

这什么时候值得做?这取决于您的数据库,索引结构和其他因素(例如,如果您将索引放在与数据不同的磁盘上),但我的经验法则是在处理表中超过10%的记录时考虑它百万条记录或更多 - 然后用测试插页检查是否值得。

当然,对于任何特定的数据库,都会有专业的批量插入例程,你也应该看看它们。

答案 2 :(得分:1)

FYI - 循环遍历记录集并在关系数据库上执行一百万次+插入,是加载表时最糟糕的情况。有些语言现在提供记录集对象。为了获得最快的性能,SMINK是正确的,使用BULK INSERT。数百万行在几分钟内完成,而不是几小时。比任何其他方法更快的数量级。

举个例子,我参与了一个电子商务项目,需要每晚刷新产品清单。插入高端Oracle数据库的100,000行需要10个小时。如果我没记错的话,那么逐行插入时的最高速度是aprox 10 recs / sec。痛苦缓慢而且完全没必要。使用批量插入 - 100K行应该不到一分钟。

希望这有帮助。

答案 3 :(得分:0)

数据来自哪里?你可以运行批量插入吗?如果是这样,那是您可以采取的最佳选择。