我有以下方法将数百万行数据插入表中(我使用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 );
}
}
答案 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)
数据来自哪里?你可以运行批量插入吗?如果是这样,那是您可以采取的最佳选择。