我正在使用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)
数据有点简化,因为列表中有更多字段。对此位置的调用(一次查询大约2000个用户)需要10秒以上,然后页面的负载也需要10-20。该表由以下主题函数first table from this link包装,虽然在某些列上禁用排序功能有帮助,但它仍然非常慢。
所以,我想知道,我如何优化此过程或生成模板以使其更快?我在带有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
的Amazon EC2实例上运行此操作。一个“明显”的解决方案,一次分页并返回100个左右的记录将真正起作用,因为列表必须包含所有用户以进行排序(主要是日期),因此该解决方案是最后的选择。
提前致谢!
答案 0 :(得分:5)
您的问题是您正在运行N + 1个查询(其中N
是User
表中的用户总数),其中1会做得更好:
User.query \
.outerjoin(Table, User.email == Table.email) \
.order_by(User.email, Table.date)
将为所有用户提供Table
按每个用户的电子邮件地址排序的所有条目,然后按Table
中的日期列。我们使用outerjoin
而不是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)
然后,您只需调用all
即可实现查询,您将参加比赛:
return render_template('users.html', list_of_users=results.all())
答案 1 :(得分:0)
首先进行异步查询。其次,维护一个条件流,你应该以块的形式显示返回的结果。 例如:
//get lenght of returning cursor
if(//length of returning cursor is greator thatn 10 or something..)
{
//Run a loop here and update your UI on UI thread for every 10 values.
}