Mysql
 sql >> Database >  >> RDS >> Mysql

Strategie di aggiornamento in blocco di SQLAlchemy

Quello che stai essenzialmente facendo è bypassare l'ORM per ottimizzare le prestazioni. Pertanto, non sorprenderti se stai "replicando il lavoro che sta facendo l'ORM" perché è esattamente quello che devi fare.

A meno che tu non abbia molti posti in cui è necessario eseguire aggiornamenti in blocco come questo, consiglierei di non utilizzare l'approccio dell'evento magico; scrivere semplicemente le query esplicite è molto più semplice.

Quello che consiglio di fare è usare SQLAlchemy Core invece dell'ORM per eseguire l'aggiornamento:

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()