我有一个当前正在使用的 Flask / Heroku 应用程序。它一直运行良好,但现在由于数量增加,我必须通过多种途径从数据库创建大量对象。我相信这就是导致我的超时错误的原因。我已将其中一些进程移至后台任务,但其他进程(例如加载主屏幕)这不是一个好的选择。我也尝试过添加测功机,但这没有帮助。我觉得必须有一种更有效的方法来做到这一点。这是一个正在崩溃的区域的示例。
events=db1.Event.query.join(db1.Event.dates_worked, aliased=True).filter(db1.Worked.date_worked.between (da , da + datetime.timedelta(days = 1))).order_by(db1.Event.items.desc()).all()
c=db1.Customer.query.filter(db1.Customer.purchase_date >= week[6]).all()
d=db1.Donor.query.filter(db1.Donor.monthly_start_date >= week[6]).all()
reps=db1.Rep.query.all()
当然,您可以对代码进行多种优化,以提高性能并减少超时错误的可能性。
减少内存中加载的对象数量:如果您一次获取太多对象,请尝试对结果进行分页或仅加载您需要的特定字段而不是整个对象。
使用预加载:默认情况下,SQLAlchemy 将使用有关关系的延迟加载,这意味着当您访问相关对象时会运行额外的查询。如果您知道您将访问这些关系,则可以使用预先加载来一次加载它们。
在过滤器中使用索引字段:确保您要过滤的字段(例如
date_worked
、purchase_date
和 monthly_start_date
)在数据库中具有适当的索引。对这些字段建立索引可以加快查询执行时间。
使用批量查询:您可以小批量查询它们,从而使查询更易于管理,而不是一次查询所有对象。
尽可能组合查询:如果可以组合某些查询,可能会减少您需要进行的查询数量。
考虑缓存:如果您的数据不经常更改,您可能需要考虑缓存结果。这可以使用 Redis 之类的东西来完成。
优化您的查询:寻找编写更高效 SQL 的机会。有时 SQLAlchemy 生成的查询不是最优的,您也许可以使用原始 SQL 编写更有效的查询。
以下是应用其中一些建议的示例:
急切加载:
from sqlalchemy.orm inside joinedload
events = (db1.Event.query
.options(joinedload(db1.Event.dates_worked))
.filter(db1.Worked.date_worked.between(da, da + datetime.timedelta(days=1)))
.order_by(db1.Event.items.desc())
.all())
仅获取特定列:
customers = db1.Customer.query.with_entities(db1.Customer.id).filter(db1.Customer.purchase_date >= week[6]).all()
批量查询:
per_page = 100
page = 1
while True:
donors = (db1.Donor.query
.filter(db1.Donor.monthly_start_date >= week[6])
.paginate(page=page, per_page=per_page, error_out=False)
.items)
if not donors:
break
# Process the batch
page += 1