SQLAlchemy bulk_save_objects 在提交时再次发出更新语句

Bir*_*e94 5 python sqlalchemy

我正在尝试使用 SQLAlchemy 的bulk_save_objects方法一次更新大量对象(大约 1000-1500)。

下面是代码的简化版本。真正的用例还包括对象的有条件创建,这就是为什么我不使用bulk_update_mappings.

对于每个对象,可以修改多个列。为了将所有更新批处理为一个查询,我使用update_changed_only=False. 我认为这没有缺点,因为无论如何所有对象都被修改了。

代码:

import random

from sqlalchemy import *
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, scoped_session
import logging

logging.basicConfig()
logger = logging.getLogger('sqlalchemy.engine')
logger.setLevel(logging.DEBUG)

# init sqlalchemy
engine = create_engine('sqlite://')
session_factory = sessionmaker(bind=engine)
Session = scoped_session(session_factory)
session = Session()

Base = declarative_base()


# simple test model
class Foo(Base):
    __tablename__ = 'test_foo'

    id = Column(Integer, primary_key=True, autoincrement=True)
    a = Column(String, default='')
    b = Column(String, default='')
    c = Column(String, default='')


# recreate database and sample data
Base.metadata.drop_all(bind=engine)
Base.metadata.create_all(bind=engine)

items = [
    Foo() for _ in range(1000)
]
session.add_all(items)
session.commit()

# query all items
items = session.query(Foo).all()

# update some items
for item in items:
    if random.random() < 0.5:
        item.a += 'a'
    if random.random() < 0.5:
        item.b += 'b'
    if random.random() < 0.5:
        item.c += 'c'

# save the objects
session.bulk_save_objects(items, update_changed_only=False)

# ... do something more

# commit the transaction
session.commit()
Run Code Online (Sandbox Code Playgroud)

预期行为:

更新在单个查询中执行。

INFO:sqlalchemy.engine.base.Engine:UPDATE test_foo SET a=?, b=?, c=? WHERE test_foo.id = ?
INFO:sqlalchemy.engine.base.Engine:(('a', 'b', 'c', 1), ('a', 'b', 'c', 2), ('a', '', '', 3), ('a', '', '', 4), ('a', '', '', 5), ('', '', 'c', 6), ('a', 'b', '', 7), ('', '', 'c', 8)  ... displaying 10 of 1000 total bound parameter sets ...  ('', 'b', '', 999), ('a', 'b', 'c', 1000))
Run Code Online (Sandbox Code Playgroud)

实际行为:

更新在单个语句中执行,然后再次作为稍微分组的更新语句执行。

bulk_update_mappings.log

SQLAlchemy 版本:

SQLAlchemy==1.2.2
Run Code Online (Sandbox Code Playgroud)

题:

我该怎么做才能避免查询运行两次?