从 db 获取数据(至 json)字段时,使用 Flask-SQLAlchemy 提高 python 的速度

Increase speed of python with Flask-SQLAlchemy when getting data (to json) fields from db

假设我有 1000 页和 10000 个标签。数据库的示例结构:

tags = db.Table('tags',
    db.Column('tag_id', db.Integer, db.ForeignKey('tag.id'), primary_key=True),
    db.Column('page_id', db.Integer, db.ForeignKey('page.id'), primary_key=True)
)

class Page(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    tags = db.relationship('Tag', secondary=tags, lazy='subquery',
        backref=db.backref('pages', lazy=True))
    page_name = db.Column(db.String(20))

class Tag(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    tag_name = db.Column(db.String(20))

我需要得到一个 json,其中包含 page_name 等字段,然后是 tag_name[=25 的列表=] 在每个 page_name 下。只有提到的字段,没有其他内容。

现在我只是像这样循环:

pages_list = []
pages = Page.query.all()
for page in pages:
    page_temp = {}
    page_name = page.page_name
    page_temp['page_name'] = page_name

    tags = []
    for tag in page.tags:
        tags.append(tag.tag_name)
    
    page_temp['tags'] = tags
    pages_list.append(page_temp)
#then return pages_list as json

但是,它给了我不希望的加载速度。有没有办法提高这里的速度并得到想要的json?

首先没有必要做pages = Page.query.all(),因为Page.query应该是一个迭代器。 它可以缩短您的查询加载时间。

其次,通过使用 lazy='subquery',您有额外的查询来为每个 page 获取 tags。您可以通过设置 lazy=joined 强制让一个查询选择所有 pagestags(它的文档:https://docs.sqlalchemy.org/en/14/orm/loading_relationships.html#joined-eager-loading)。因此,当您执行 page.tags 时,不会命中其他隐式查询(您将有 1 个查询而不是 <number of pages> + 1 查询)。问题是你是不是总是想在获取page的时候获取tags?如果没有,您可以在查询端使用 joinedload

from sqlalchemy.orm import joinedload

pages_list = []
pages = Page.query.options(joinedload(Page.tags))
for page in pages:
    page_temp = {}
    page_name = page.page_name
    page_temp['page_name'] = page_name

    tags = []
    for tag in page.tags:
        tags.append(tag.tag_name)
    
    page_temp['tags'] = tags
    pages_list.append(page_temp)
#then return pages_list as json

呈现包含大量关联标签的 10k 页面结构总是需要一些时间。您可以考虑对这些数据进行分页吗?或者您必须在一个请求中获取它?