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

Django视图中查询近7天每日预订量的数据库操作最佳实践咨询

Django View层数据库查询优化解答

原写法问题分析

第一种7次filter的写法

  • 结论:完全不合理,且确实会触发7次独立的数据库查询
  • 额外问题:你用len()计算查询集长度的写法也有性能问题:len()会把符合条件的所有行全部加载到Django服务内存中再统计数量,远不如直接调用QuerySet.count()(直接在数据库层执行SELECT COUNT(*),不需要传输全量数据)效率高。

第二种全量遍历的写法

  • 结论:比第一种写法性能更差,绝对不推荐
  • 问题:该写法会把所有is_reserved=True的预订数据全部加载到内存中遍历,如果你的业务预订量达到千级/万级以上,会直接占用大量内存,甚至导致服务OOM,完全违背了数据库本身擅长聚合运算的设计逻辑。

最佳实践方案

Django ORM原生支持分组聚合能力,你要的过去7天每日有效预订量,只需要1次数据库查询即可完成,性能远高于上述两种写法:

第一步:导入依赖

from django.db.models import Count
from datetime import timedelta
# 如果你的存储字段是DateTime类型而非Date类型,还需要导入:
# from django.db.models.functions import TruncDate

第二步:执行分组聚合查询

# 先计算过去7天的起始日期
start_date = TODAY_DATE - timedelta(days=6)

# 一次查询完成按日期分组统计
daily_reserve_counts = Reservations.objects.filter(
    is_reserved=True,
    date__range=(start_date, TODAY_DATE)
).values('date').annotate(
    daily_count = Count('id') # 按日期分组统计数量
).order_by('date')

返回结果格式示例:

<QuerySet [{'date': datetime.date(2024,5,1), 'daily_count': 12}, {'date': datetime.date(2024,5,2), 'daily_count': 7}, ...]>

可选:补全无预订的日期

如果某一天没有有效预订,聚合结果默认不会返回该日期的记录,如果你需要保证返回7天的完整数据,可以自行构造默认值字典:

# 初始化7天的默认统计值为0
result = {TODAY_DATE - timedelta(days=i):0 for i in range(7)}
# 把查询结果填充到默认字典中
for item in daily_reserve_counts:
    result[item['date']] = item['daily_count']

额外优化建议

  • 可以给date和is_reserved字段加联合索引,进一步加快查询速度
  • 如果你的日期字段是DateTime类型,分组前需要先截断为日期:
    daily_reserve_counts = Reservations.objects.filter(
        is_reserved=True,
        create_time__range=(start_date, TODAY_DATE)
    ).annotate(
        date = TruncDate('create_time')
    ).values('date').annotate(
        daily_count = Count('id')
    ).order_by('date')
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 13:18:03