我开始做一些我认为会直截了当的事情:顺序(逐行)读取,计算一些值并更新同一行,然后再进入整个表的下一行。
上下文:单个平面表, 2600万条记录,复合PK(4个数值)。 物理表大小1.3 GB 。处理记录的顺序无关紧要。这将仅在可预见的将来进行一次。计算它太复杂了,无法在SQL中完成(对我来说至少: - )
建议的有效方法是什么?
我尝试了什么:在datareader
中使用ADO.NET
(它已经没有那么好的旧VB6结果集了,这本来就更简单了)。在每个reader.Read()
循环中将它与更新语句(statement.ExecuteNonQuery)相结合是很棘手的,因为ADO.NET不喜欢在同一个连接上。所以我不得不打开2个连接。 (更新查询使用WHERE子句中的复合PK,它可能很快,但由于光标已经在我即将更新的记录中,因此效率低下仍然让我感到低效。)
这种方法有效,但不适用于基于SELECT * FROM MyTable
查询的阅读器。我不得不使用LIMIT
一次读取几千行的块来避免超时错误。从早期的实验中我估计了2600万条记录的强度> 9小时。我把它设置为一夜之间运行,当我回来的时候,在整个过程中三分之一的时间再次超时。重新启动后,我发现一旦偏移量变大,LIMIT子句会减慢SELECT
查询的速度。我对其余65%的新估计超过了另外20个小时,可能更长,因为LIMIT抵消增加。
必须有更好的方法!?
(我也尝试了优雅的EF,但当然超时了: - )
答案 0 :(得分:0)
小批量更新数据库(1000个左右的记录)通常是一种很好的方法,因为它可以避免长时间锁定行(或页面),并避免超时。这部分方法很棒。
您可以针对较大的起始值提高LIMIT的性能。有各种方法。我发现迄今为止最好的是根本不使用LIMIT,而是选择主键范围
答案 1 :(得分:0)
经过上述与Eric的讨论和进一步的实验,这是我对传奇的结论:
希望这可以帮助处于类似情况的任何人。非常感谢评论。