【发布时间】:2020-12-28 07:22:10
【问题描述】:
我有一个运行 SQLAlchemy 和 PostgresQL 的 Flask 应用程序来处理大量数据。我们在前端显示的其中一件事是仪表板,其中包含给定组织的多个汇总统计信息。最近这个端点运行得非常慢,所以我一直在尝试优化它并提高性能。
我首先对 BaseQuery 进行子类化,并在 .count() 中实现了一个更精简的 SQLAlchemy 版本,它在不使用子查询的情况下也很重要。
优化查询
from sqlalchemy import func
from sqlalchemy.orm import lazyload
from flask_sqlalchemy import BaseQuery
class OptimisedQuery(BaseQuery):
def optimised_count(query):
count_query = query.options(lazyload('*')).statement.with_only_columns([func.count()]).order_by(None)
return query.session.execute(count_query).scalar()
api/dashboard.py
@dashboards.route("/api/dashboard/stats", methods=["GET"])
@authentication_required
def stats(current_user):
org = current_user.organization
total_subscribers = Subscriber.query.filter_by(
unsubscribed=False, organization=org
).optimised_count()
total_conversations = SubscriberConversationState.query.filter_by(
organization=org
).optimised_count()
total_messages = Message.query.filter_by(
organization=org
).optimised_count()
total_unsubscribers = Subscriber.query.filter_by(
unsubscribed=True, organization=org
).optimised_count()
return jsonify(
dict(
total_subscribers=total_subscribers,
total_conversations=total_conversations,
total_messages=total_messages,
total_unsubscribers=total_unsubscribers,
)
)
这绝对是朝着正确方向迈出的一步,显着降低了端点延迟。话虽如此,加载仍然需要 9 到 15 秒,所以我深入到 New Relic 并看到其中一个查询(在消息表上计数)仍然执行得很糟糕。下面的截图实际上是我能找到的最好的,大约 1.5 秒,但有时需要 6 秒。
这并不那令人惊讶,因为消息表是其中最大的(4,090,065 行)。然而,查看查询,它似乎尽可能精简,即使我要放弃 SQLAlchemy 并只编写纯 SQL。更奇怪的是,在将 prod db 克隆到我的本地计算机并使用 pgbench 分析相同的查询后,查询运行得很快,平均延迟为 86.9 毫秒。
问题
- 最终的精简查询
SELECT count(*) AS count_1 FROM message WHERE %(param_1)s = messages.organization_id是查询所能得到的最精简的吗? - 我找到了大量关于
COUNT性能和提高性能的策略的文章,但没有找到COUNT WHERE查询的文章。是 我可以在我的数据库构建中做一些事情来加快它 这个案例? (索引等) - 什么可能导致
pgbench86.9 毫秒的延迟和超过 6 秒的生产运行时间之间的差异?供参考, 应用程序托管在 Heroku 上,并利用 3 个 Standard-2X web dynos 和一个 Postgres Standard-0 插件。
【问题讨论】:
-
只是几个想法:如果您的生产环境正在处理来自许多不同用户的请求,而您的本地环境仅处理来自您的请求,那么这可能会产生重大影响。此外,如果您的 pgbench 测试连续 50 次运行相同的查询,那么第一次迭代可能会相当慢,而接下来的 49 次迭代会快得多(由于缓存),因此这 50 次迭代的平均值可能会严重向下偏差。跨度>
标签: postgresql flask heroku sqlalchemy