SQLAlchemy中所有行的高效更新
Posted
技术标签:
【中文标题】SQLAlchemy中所有行的高效更新【英文标题】:Efficient Update of All Rows in SQLAlchemy 【发布时间】:2020-02-19 03:13:03 【问题描述】:我目前正在尝试更新表中的所有行,方法是根据同一行中另一列 source_images
的值设置一列 images
的值。
for row in Cars.query.all():
# Generate a list of strings
images = [s for s in row.source_images if 'example.com/' in s]
# Column 'images' being updated is a sqlalchemy.dialects.postgresql.ARRAY(Text())
Cars.query.filter(Cars.id == row.id).update('images': images)
db_session.commit()
问题:这似乎真的很慢,尤其是在应用于 100k+ 行时。有没有更有效的更新行的方法?
类似问题:
#1:这个问题涉及通过增加值来更新所有行。
模型类定义:cars.py
from sqlalchemy import *
from sqlalchemy.dialects import postgresql
from ..Base import Base
class Car(Base):
__tablename__ = 'cars'
id = Column(Integer, primary_key=True)
images = Column(postgresql.ARRAY(Text))
source_images = Column(postgresql.ARRAY(Text))
【问题讨论】:
【参考方案1】:您可以将操作带到数据库,而不是单独获取和更新每一行:
from sqlalchemy import select, column, func
source_images = select([column('i')]).\
select_from(func.unnest(Car.source_images).alias('i')).\
where(column('i').contains('example.com/'))
source_images = func.array(source_images)
Car.query.update(Car.images: source_images,
synchronize_session=False)
相关子查询将源图像取消嵌套,选择符合条件的图像,ARRAY()
constructor 形成新的图像数组。
您也可以使用array_agg()
:
source_images = select([func.array_agg(column('i'))]).\
select_from(func.unnest(Car.source_images).alias('i')).\
where(column('i').contains('example.com/'))
【讨论】:
在这台机器上,使用本地数据库,更新 500,000 行包含随机源图像数组的行大约需要 5 秒,其中包含“example.com/”且 P >= 10%。以上是关于SQLAlchemy中所有行的高效更新的主要内容,如果未能解决你的问题,请参考以下文章