我需要在表上更新大约250k行,并且每个要更新的字段将具有不同的值,具体取决于行本身(不是基于行ID或键计算的,而是根据外部计算)。
我尝试使用参数化查询,但事实证明它很慢(我仍然可以在SQL Server 2008中尝试使用表值参数SqlDbType.Structured,但我想有一个通用的方法来执行它在几个数据库上,包括MySql,Oracle和Firebird)。
制作大量的个人更新也很慢(比使用参数化查询进行数千次单独调用(往返!)快2倍)
如何创建临时表并运行加入我的表和tmp的更新?会更快地运作吗?
答案 0 :(得分:7)
“慢”的速度有多慢?
这个问题的主要问题是它会在数据库的日志文件中创建一个巨大的条目(如果在更新过程中出现电源故障,数据库需要记录每个操作,它可以在发生故障时回滚)。这很可能是“缓慢”的来源,而不是其他任何东西(尽管显然有如此多的行,还有其他方法可以使事情效率低下[例如,每次更新一次DB往返会非常缓慢] ,我只是说,一旦你消除了明显的事情,你仍然会发现它很慢。)
有几种方法可以更有效地完成它。比如,一个是以块的形式进行更新,一次1000行。这样,数据库就会写出许多小的日志条目,而不是一个非常庞大的日志条目。
另一种方法是关闭 - 或者“关闭” - 数据库在更新期间的日志记录。例如,在SQL Server中,您可以将Recovery Model设置为“简单”或“批量更新”,这会大大加快速度(请注意,如果出现电源故障,您会面临更大风险)更新)。
编辑为了进一步扩展,可能首先实际执行查询的最有效方法是将所有新行的BULK INSERT放入临时表中,然后从那里做一个现有表格的UPDATE
(或者如上所述,以1000块为单位进行UPDATE
)。我的大多数答案都是在你实现它之后解决这个问题:你仍然会发现它很慢......
答案 1 :(得分:3)
如果可能,请调用存储过程
答案 2 :(得分:2)
如果更新的列是您可以
的索引的一部分如果您需要这些索引来检索数据,那么它无济于事。
答案 3 :(得分:1)
您应该使用SqlBulkCopy并设置KeepIdentities标志。
作为SqlTransaction的一部分,执行查询以选择所有需要更新的记录,然后删除它们,返回那些选定(现在已删除)的记录。一次性将它们读入C#。在内存中更新C#端的记录,现在您已经缩小了选择范围,然后SqlBulkCopy更新了那些更新的记录,键和所有记录。并且不要忘记提交交易。这是更多的工作,但速度非常快。
答案 4 :(得分:0)
这就是我要做的事情:
优点:
缺点:
答案 5 :(得分:0)
以下内容可能会使您的更新速度变慢: