Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Estratégias de atualização em massa do SQLAlchemy


O que você está fazendo essencialmente é ignorar o ORM para otimizar o desempenho. Portanto, não se surpreenda por você estar "replicando o trabalho que o ORM está fazendo", porque é exatamente isso que você precisa fazer.

A menos que você tenha muitos lugares onde você precisa fazer atualizações em massa como esta, eu recomendaria contra a abordagem de eventos mágicos; simplesmente escrever as consultas explícitas é muito mais direto.

O que eu recomendo fazer é usar o SQLAlchemy Core ao invés do ORM para fazer a atualização:
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()