我有一个遍历数百万个对象的for循环。提出这个建议的方法是什么?以下是我想到的一些例子:
# after each
for item in items:
cursor.execute()
conn.commit()
# at the end
for item in items:
cursor.execute()
conn.commit()
# after N items
for n, item in enumerate(items):
cursor.execute()
if n % N == 0:
conn.commit()
conn.commit()
以上哪项最有效?
答案 0 :(得分:4)
你问,我应该承诺......
首先,如果您正在使用MyISAM,请不要担心。 MyISAM没有实现交易。
如果您的系统仅通过提交部分行更改而不会被破坏,则应在每N个项目之后提交。这是因为在每个项目之后进行操作会大大减慢您的处理速度。只有在庞大的操作结束时才提交一次,可能会导致您的回滚空间不足,或者在其他数据库用户出现减速的情况下花费不可思议的长时间。
我经历过无数次。任何大于约20的N都可以。
答案 1 :(得分:1)
可以说#"在最后"一个,因为您BEGIN
和COMMIT
只有一次,并且它是一个具有自己范围的单个事务。从并发的角度来看,它更容易:基本上交易说:现在这是我的桌子,不要碰任何人。
如果你多次提交(另外两个解决方案),你多次BEGIN
和COMMIT
一次交易(在你提交后立即开始下一个交易)。这意味着其他正在进行的数据库操作中断的可能性更大。此外 - 这些操作本身需要时间。
但是,您应该运行模拟用例的基准测试。我很想知道是否取决于某些条件(要插入的行数,会话配置,数据类型,使用的索引),可能会有一种或另一种解决方案占上风。