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

Django Lazy Querysets优化:销售仪表板页面加载缓慢求助

优化销售仪表板数据库查询性能的方案

看起来你遇到的是典型的重复数据库查询导致的性能问题,我来给你几个针对性的优化方案,应该能大幅提升页面加载速度:

1. 批量聚合查询,一次获取所有指标

你现在每个指标单独过滤查询的方式会导致多次数据库往返,最有效的解决办法是用Django的aggregate结合filter,一次查询计算出所有需要的统计值。这样不管有多少个指标,只需要一次数据库请求就能拿到结果。

示例代码:

from django.db.models import Count, Q
from datetime import timedelta
from django.utils import timezone

# 定义时间范围(替换成你的X、Y值)
x_days_ago = timezone.now() - timedelta(days=7)
y_days_ago = timezone.now() - timedelta(days=14)

# 一次查询聚合所有指标
dashboard_metrics = Opportunities.objects.aggregate(
    # 近X天赢单机会数
    recent_won_count=Count('id', filter=Q(status='won', created_at__gte=x_days_ago)),
    # Y天无活动的待跟进机会数
    inactive_followup_count=Count('id', filter=Q(status='pending', last_activity__lte=y_days_ago)),
    # 其他指标可以继续在这里添加,比如总待跟进数、本月新增数等
    total_pending_count=Count('id', filter=Q(status='pending'))
)

# 使用时直接取字典里的对应值
won_count = dashboard_metrics['recent_won_count']
inactive_count = dashboard_metrics['inactive_followup_count']

2. 检查QuerySet是否被重复求值

你提到提前获取了QuerySet再传入各函数,但如果每个函数里对这个QuerySet做过滤后又触发了求值(比如调用len()、遍历或者转成列表),每个过滤后的QuerySet还是会单独执行一次SQL查询。这种情况下,批量聚合依然是最优解,因为它直接在数据库层面完成所有统计,不需要拉取大量数据到内存。

3. 给过滤字段添加数据库索引

你的查询用到了status、created_at、last_activity这些字段,给这些字段组合添加索引能大幅提升数据库的查询效率。

在你的Opportunities模型中添加索引:

class Opportunities(models.Model):
    # 你的其他字段定义
    status = models.CharField(max_length=50)
    created_at = models.DateTimeField(auto_now_add=True)
    last_activity = models.DateTimeField(auto_now=True)

    class Meta:
        indexes = [
            # 针对赢单指标的组合索引
            models.Index(fields=['status', 'created_at']),
            # 针对无活动待跟进指标的组合索引
            models.Index(fields=['status', 'last_activity']),
        ]

添加后记得运行python manage.py makemigrations和python manage.py migrate来应用索引。

4. 给统计结果添加缓存

销售仪表板的统计指标通常不需要实时更新(比如5-10分钟更新一次就足够),可以用Django的缓存框架把聚合结果缓存起来,避免每次请求都查数据库。

示例代码:

from django.core.cache import cache

def get_dashboard_metrics():
    cache_key = 'sales_dashboard_metrics'
    # 先尝试从缓存获取
    metrics = cache.get(cache_key)
    if not metrics:
        # 如果缓存不存在,执行聚合查询
        x_days_ago = timezone.now() - timedelta(days=7)
        y_days_ago = timezone.now() - timedelta(days=14)
        metrics = Opportunities.objects.aggregate(
            recent_won_count=Count('id', filter=Q(status='won', created_at__gte=x_days_ago)),
            inactive_followup_count=Count('id', filter=Q(status='pending', last_activity__lte=y_days_ago))
        )
        # 缓存5分钟(根据你的业务需求调整过期时间)
        cache.set(cache_key, metrics, 60*5)
    return metrics

5. 验证查询次数(可选)

可以安装django-debug-toolbar来直观查看页面请求触发的数据库查询次数,确认优化后是否减少了查询。安装后,页面会显示每个请求的SQL查询列表,你能清楚看到优化前后的变化。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 08:38:01