Mysql
 sql >> Base de données >  >> RDS >> Mysql

Stratégies de mise à jour en masse de SQLAlchemy

Ce que vous faites essentiellement, c'est contourner l'ORM afin d'optimiser les performances. Par conséquent, ne soyez pas surpris que vous « reproduisiez le travail que fait l'ORM », car c'est exactement ce que vous devez faire.

À moins que vous n'ayez de nombreux endroits où vous devez effectuer des mises à jour groupées comme celle-ci, je vous déconseille l'approche des événements magiques ; écrire simplement les requêtes explicites est beaucoup plus simple.

Ce que je recommande, c'est d'utiliser SQLAlchemy Core au lieu de l'ORM pour effectuer la mise à jour :

ledger = Table("ledger", db.metadata,
    Column("wallet_id", Integer, primary_key=True),
    Column("new_balance", Float),
    prefixes=["TEMPORARY"],
)


wallets = db_session.query(Wallet).all()

# figure out new balances
balance_map = {}
for w in wallets:
    balance_map[w.id] = calculate_new_balance(w)

# create temp table with balances we need to update
ledger.create(bind=db.session.get_bind())

# insert update data
db.session.execute(ledger.insert().values([{"wallet_id": k, "new_balance": v}
                                           for k, v in balance_map.items()])

# perform update
db.session.execute(Wallet.__table__
                         .update()
                         .values(balance=ledger.c.new_balance)
                         .where(Wallet.__table__.c.id == ledger.c.wallet_id))

# drop temp table
ledger.drop(bind=db.session.get_bind())

# commit changes
db.session.commit()