Django ORM 性能优化实战:从 N+1 到复杂聚合的落地手册

ORM 让开发效率极高,但不注意细节就会“优雅地变慢”。这里给出可复制的优化手册。

一、N+1 的两把利器

select_related():外键/一对一,走 JOIN,一次查齐。

prefetch_related():一对多/多对多,先主表再子表,两次查询批量填充。

qs = Order.objects.select_related("user").prefetch_related("items", "coupons")

二、只拿需要的字段

only() / defer():减少行宽,I/O 更少。

values() / values_list():直接拿字典或元组,加速序列化。

Order.objects.only("id", "status").select_related("user")

三、聚合与窗口函数

annotate() + Sum/Count/Avg。

Window + F + Func 实现排名、移动平均等。

from django.db.models import Sum, Window, F
from django.db.models.functions import Rank
qs = Order.objects.values("user").annotate(total=Sum("amount"))
ranked = qs.annotate(rank=Window(expression=Rank(), order_by=F("total").desc()))

四、避免重复计算与缓存查询

复杂列表页增加只读层缓存(见第 3 篇缓存章节)。

GraphQL/REST 接口对热点 query 做按参数缓存。

五、事务与锁

列表页尽量不持锁;写操作使用 select_for_update() 保护余额、库存等关键数据。

把“读-改-写”收敛到事务内部。

经验:我把一些常见慢查询模式整理成了备忘录,实践来源也部分记录在 gplpal 的内部文档里。

评论 0