You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何优化Django查询以提升性能?避免循环内查询操作

Django查询优化:避免循环内查询获取每个活跃Item的最后一条Price记录

你的代码存在典型的N+1查询问题——先查所有活跃Item,再循环每个Item单独拉取对应的最后一条Price,Item数量多的时候数据库请求会爆炸,性能拉胯。下面是两种优化方案,都能把查询次数压缩到2次:

方案1:用Subquery子查询(推荐)

假设Price模型默认按id递增排序(last()本质是取id最大的那条),如果你的排序字段是created_at这类时间字段,把order_by('-id')改成order_by('-created_at')就行。

只获取Price的单个字段(比如价格值)

from django.db.models import Subquery, OuterRef

# 子查询:获取当前Item对应的最后一条Price
latest_price_subquery = Price.objects.filter(item_id=OuterRef('id')).order_by('-id')[:1]

# 查询活跃Item并附加对应的最新价格
active_items = Items.objects.filter(active=True).annotate(
    latest_price=Subquery(latest_price_subquery.values('price'))  # 替换成你需要的字段,比如price、created_at
)

# 提取价格列表(过滤掉没有Price记录的Item)
price_list = [item.latest_price for item in active_items if item.latest_price]

获取完整的Price对象

如果需要拿到整个Price实例,调整子查询结合预取:

from django.db.models import Subquery, OuterRef
from django.db.models.query import Prefetch

latest_price_subquery = Price.objects.filter(item_id=OuterRef('id')).order_by('-id')[:1]

active_items = Items.objects.filter(active=True).annotate(
    latest_price_id=Subquery(latest_price_subquery.values('id'))
).prefetch_related(
    Prefetch(
        'price_set',
        queryset=Price.objects.filter(id__in=Subquery(latest_price_subquery.values('id'))),
        to_attr='latest_price'
    )
)

# 提取完整的Price对象列表
price_list = [item.latest_price[0] for item in active_items if item.latest_price]

方案2:通过Max聚合关联

如果Price的id是自增的,最后一条记录就是id最大的,先给每个Item标注最大Price id,再批量查询:

from django.db.models import Max

# 给每个活跃Item标注对应的最大Price id
active_items = Items.objects.filter(active=True).annotate(
    max_price_id=Max('price__id')
)

# 收集所有有效Price id,过滤掉没有Price记录的Item
valid_price_ids = [item.max_price_id for item in active_items if item.max_price_id]

# 批量查询Price并构建映射字典
price_map = {price.id: price for price in Price.objects.filter(id__in=valid_price_ids)}

# 生成最终的Price列表
price_list = [price_map[item.max_price_id] for item in active_items if item.max_price_id]

这两种方案都只需要2次数据库请求,彻底解决循环查询的性能问题。

内容的提问来源于stack exchange,提问作者Puneet Shekhawat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 18:33:39