我有一张包含1.400.000条目的表格。它是一个简单的文件清单
表格 - 文件
我扫描目录并将目录中找到的任何文档设置为有效。
public void SetReportsToValidated(List<int> validatedReports)
{
SqlConnection myCon = null;
try
{
myCon = new SqlConnection(_conn);
myCon.Open();
foreach (int id in validatedReports)
{
SqlDataAdapter myAdap = new SqlDataAdapter("update_DocumentValidated", myCon);
myAdap.SelectCommand.CommandType = CommandType.StoredProcedure;
SqlParameter pId = new SqlParameter("@Id", SqlDbType.Int);
pId.Value = id;
myAdap.SelectCommand.Parameters.Add(pId);
myAdap.SelectCommand.ExecuteNonQuery();
}
}
catch (SystemException ex)
{
_log.Error(ex);
throw;
}
finally
{
if (myCon != null)
{
myCon.Close();
}
}
}
更新的表现还可以,但我想要更多。将1000000个文档更新为有效需要1个多小时。有没有什么好方法可以加快更新速度?我正在考虑使用某种批处理(如表值参数)。 在SQLServer上进行配置时,每次更新大约需要5-10ms。
答案 0 :(得分:2)
阅读报告并将它们一起添加到DataTable中(因为它们具有相同的维度),然后使用SqlBulkCopy对象上传整个内容。可能会更适合你。鉴于列数和行数很少,我认为你不会遇到内存问题。
答案 1 :(得分:2)
此时您正在为每条记录单独调用数据库。您可以使用SqlDataAdapter进行批量更新(简而言之):
1)定义一个SqlDataAdapter
2)将适配器上的.UpdateCommand设置为更新分组
3)在适配器上调用.Update方法,向其传递包含要更新的文档的ID的DataTable。这会将更新的行从DataTable批处理到DB,以批处理方式为每个记录调用sproc。您可以通过.BatchSize属性控制批量大小
4)所以你正在做的是删除手动,逐行循环,这对于批量更新是低效的。
见例子:
http://support.microsoft.com/kb/308055
http://www.c-sharpcorner.com/UploadFile/61b832/4430/
或者,你可以:
1)使用SqlBulkCopy将所有ID批量插入数据库中的 new 表(高效)
2)加载到该临时表后,运行单个SQL语句以从该临时表更新主表以验证文档。
见例子:
http://www.adathedev.co.uk/2010/02/sqlbulkcopy-bulk-load-to-sql-server.html
http://www.adathedev.co.uk/2011/01/sqlbulkcopy-to-sql-server-in-parallel.html
答案 2 :(得分:0)
不是每次在循环中创建适配器和参数,只需创建一次并为参数指定不同的值:
SqlDataAdapter myAdap = new SqlDataAdapter("update_DocumentValidated", myCon);
myAdap.SelectCommand.CommandType = CommandType.StoredProcedure;
SqlParameter pId = new SqlParameter("@Id", SqlDbType.Int);
myAdap.SelectCommand.Parameters.Add(pId);
foreach (int id in validatedReports)
{
myAdap.SelectCommand.Parameters[0].Value = id;
myAdap.SelectCommand.ExecuteNonQuery();
}
这可能不会带来非常显着的改善,但与原始代码相比更好。此外,当您手动执行SqlCommand对象时,根本不需要适配器。只需直接使用SqlCommand。