查询数据库时提高页面速度

won*_*ile 1 mysql query-optimization jinja2 flask flask-sqlalchemy

我正在使用Flask进行我正在使用的一个应用程序,以及用于存储数据的sqlalchemy和MySQL数据库.Jinja2用于模板化.在开发过程中,一切都很好,但是现在当使用更大的数据集时,我对包含大量数据的一些网页的呈现速度非常慢.例如,此代码处理用户列表:

def users():
    q = Users.query.all()
    out = []
    for i in q: 
        try:
            something_i_need = Table.query.filter_by(email=i.email).order_by(Table.date).first().id
        except:
            something_i_need = 0
        out.append({
                'id': i.id,
                'last_name': i.last_name,
                'first_name': i.first_name,
                'middle_name': i.middle_name,
                'phone': i.phone,
                'team': i.team,
                'status': i.status,
                'needed': something_i_need,
                'some_more_data': i.some_more_data
            })
    return render_template('users.html', list_of_users=out)
Run Code Online (Sandbox Code Playgroud)

数据有点简化,因为列表中有更多字段.对此位置的调用(一次查询大约2000个用户)需要10秒以上,然后页面的负载也需要10-20.该表由以下主题函数包装,来自此链接的第一个表,虽然在某些列上禁用排序功能有帮助,但它仍然非常慢.

所以,我想知道,我如何优化此过程或生成模板以使其更快?我在Amazon EC2实例上运行它Python 2.7.3 and mod_wsgi, Flask 0.9, Flask-SQLAlchemy=0.16, Jinja2==2.7, MySQL-python=1.2.4, SQLAlchemy=0.8.1.一个"明显"的解决方案,一次分页并返回100个左右的记录将真正起作用,因为列表必须包含所有用户以进行排序(主要是日期),因此该解决方案将是最后的手段.

提前致谢!

Sea*_*ira 5

您的问题是您正在运行N + 1个查询(表中N的用户总数User),其中1会做得更好:

User.query \
        .outerjoin(Table, User.email == Table.email) \
        .order_by(User.email, Table.date)
Run Code Online (Sandbox Code Playgroud)

将为您的所有用户提供Table按每个用户的电子邮件地址排序的所有条目,然后按日期列Table.我们使用an outerjoin而不是a join来确保我们获得用户,即使他们没有条目Table.

现在,这不是我们需要的 - 我们真的想要获得最新的条目(Table如果存在的话).可能有更好的方法来做到这一点,但这是一个子查询的简单示例:

last_entry = Table.query \
                  .group_by(Table.email) \
                  .order_by(Table.date) \
                  .subquery()

# Assuming that db is your Flask-SQLAlchemy extension
results = db.session.query(User, last_entry.c.id)  \
    .outerjoin(last_entry, User.email == last_entry.c.email)
Run Code Online (Sandbox Code Playgroud)

然后你可以通过调用来实现查询,all你将参加比赛:

return render_template('users.html', list_of_users=results.all())
Run Code Online (Sandbox Code Playgroud)