订单列表加载三秒以上,慢查询日志里同一条语句重复执行几十次。日志里能对上时间点,这种反而好排。

循环里逐条查询关联数据,查询次数与列表长度成正比。这一点先确认清楚,后面就不用反复试。

ids = [o.user_id for o in orders]
users = {u.id: u for u in session.query(User).filter(User.id.in_(ids))}
for o in orders:
    o.user = users.get(o.user_id)

「接口 N+1 查询」排查到最后往往是很小的一处差异,前面那些复杂猜测可以先放一放。线上出问题先对时间点,跟发布、备份、任务执行的时刻排一排,能省掉一半功夫。

日志级别临时调高可以,记得改回去,长期开着既占磁盘又掩盖真问题。权限不要一口气开到最大,先加到够用再往上试,范围小才好收。

把复现步骤压到三条以内,交给同事也能跑出来,才算真的定位清楚。改动写完就同步给同事,下一个人踩同一个坑,成本还是你的。

处理上按这个顺序:改为批量按 id 集合查询;在内存里做映射;必要时用联表一次取回。

结果对不对很好判断,列表接口查询次数降到常数级,响应时间明显下降。

作者 9823189