【问题标题】:Using bulk_update_mappings in SQLAlchemy to update multiple rows with different values在 SQLAlchemy 中使用 bulk_update_mappings 更新具有不同值的多行
【发布时间】:2016-07-16 07:13:39
【问题描述】:

我有两张桌子 Foo 和 Bar。我刚刚在 Bar 表中添加了一个新列 x,它必须使用 Foo 中的值来填充

class Foo(Base):
    __table__ = 'foo'
    id = Column(Integer, primary_key=True)
    x = Column(Integer, nullable=False)

class Bar(Base):
    __table__ = 'bar'
    id = Column(Integer, primary_key=True)
    x = Column(Integer, nullable=False)
    foo_id = Column(Integer, ForeignKey('foo.id'), nullable=False)

一种直接的方法是遍历 Bar 中的所有行,然后逐个更新它们,但这需要很长时间(Foo 和 Bar 中有超过 100k 行)

for b, foo_x in session.query(Bar, Foo.x).join(Foo, Foo.id==Bar.foo_id):
    b.x = foo_x
session.flush()

现在我想知道这是否是正确的做法 -

mappings = []
for b, foo_x in session.query(Bar, Foo.x).join(Foo, Foo.id==Bar.foo_id):
    info = {'id':b.id, 'x': foo_x}
    mappings.append(info)
session.bulk_update_mappings(Bar, mappings)

bulk_update_mappings 上的例子不多。文档建议

所有存在且不属于主键的键 应用于 UPDATE 语句的 SET 子句;主键 需要的值应用于 WHERE 子句。

那么,在这种情况下,id 将在 WHERE 子句中使用,然后使用字典中的 x 值进行更新,对吗?

【问题讨论】:

  • @Chris,我认为这对你有用,你只是想确保从方法的角度来看方法是正确的?
  • 是的,正是……

标签: python mysql sqlalchemy


【解决方案1】:

该方法在使用方面是正确的。我唯一要改变的是下面的内容

mappings = []
i = 0

for b, foo_x in session.query(Bar, Foo.x).join(Foo, Foo.id==Bar.foo_id):
    info = {'id':b.id, 'x': foo_x}
    mappings.append(info)
    i = i + 1
    if i % 10000 == 0:
        session.bulk_update_mappings(Bar, mappings)
        session.flush()
        session.commit()
        mappings[:] = []

session.bulk_update_mappings(Bar, mappings)

这将确保您没有太多的数据挂在内存中,并且您不会一次对数据库进行太大的插入

【讨论】:

  • 太棒了!我有数百万数据要更新,sql 和后端之间的连接很差。似乎更新过程永远挂起。感谢拆分数据的建议。
  • 有没有办法将where子句指定为主键以外的字段?
  • @Mehrdad,我建议打开一个新查询并在需要时在此处发布链接。因为问题完全不同
  • @TarunLalwani 好建议,我做到了:stackoverflow.com/questions/57534134/…
  • 默认情况下,会话已启用自动刷新,因此无需每 10k 条记录显式刷新
猜你喜欢
  • 2019-08-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-29
  • 2023-03-23
相关资源
最近更新 更多