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