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

如何优化面向React前端数据表页面的Django API响应性能?

Django deployed_data接口性能优化方案

你这段代码8条数据耗时超过3秒,核心问题基本都是循环遍历触发N+1数据库查询+不必要的模型实例化/计算开销,按优先级落地以下优化即可,改完后8条数据的响应耗时通常能降到20ms以内:

  • 优先解决外键关联的N+1查询问题
    你在循环中访问dep.PLATFORM_TYPE.VALUE和dep.DEPLOYMENT_PLATFORM.VALUE时,每遍历一条记录都会单独发起一次SQL查询关联表,8条记录仅这两处就会产生16次额外的数据库往返,这是最主要的耗时来源。
    用select_related在初始查询时就通过JOIN把关联表数据一次性查出来,后续访问关联对象不会再触发额外查询:

    deployments = deployment.objects.filter(
        LAUNCH_DATE__isnull=False,
        HISTORICAL=False
    ).select_related("PLATFORM_TYPE", "DEPLOYMENT_PLATFORM")
    
  • 排查模型属性的隐式查询,把计算逻辑下沉到数据库层
    你代码里用到的status、last_report、next_report、days_since_last、last_cycle、age如果是模型上用@property定义的计算属性,先检查这些属性内部有没有数据库查询逻辑——如果有,不要在Python循环里逐行计算,用annotate把计算逻辑放到数据库侧一次性完成。
    比如age是部署时间到当前时间的天数,完全可以在查询时直接算好:

    from django.db.models import F, ExpressionWrapper, DurationField
    from django.utils import timezone
    
    deployments = deployments.annotate(
        age_cal=ExpressionWrapper(
            timezone.now() - F("LAUNCH_DATE"),
            output_field=DurationField()
        )
    )
    # 后续取值直接拿dep.age_cal.days即可,不用逐行触发Python侧的计算逻辑
    
  • 用values()直接取需要的字段,省掉模型实例化开销
    你当前的查询会把deployment表所有字段都加载成模型实例,很多不需要的字段会浪费内存和查询时间。直接用values()指定需要返回的字段,连逐行拼字典的步骤都能省大半:

    from django.db.models.functions import DateFormat, DateTimeFormat
    
    deployments = deployment.objects.filter(
        LAUNCH_DATE__isnull=False,
        HISTORICAL=False
    ).select_related("PLATFORM_TYPE", "DEPLOYMENT_PLATFORM").annotate(
        # 直接在数据库层完成日期格式化,省掉Python层strftime的开销
        LAUNCH_DATE=DateFormat("LAUNCH_DATE", "%Y-%m-%d"),
        last_report=DateTimeFormat("last_report", "%Y-%m-%d %H:%M"),
        next_report=DateTimeFormat("next_report", "%Y-%m-%d %H:%M"),
        age_cal=ExpressionWrapper(timezone.now() - F("LAUNCH_DATE"), output_field=DurationField()),
        # 直接取关联表的字段值,不用后续再从关联对象里取
        PLATFORM_TYPE=F("PLATFORM_TYPE__VALUE"),
        DEPLOYMENT_PLATFORM=F("DEPLOYMENT_PLATFORM__VALUE")
    ).values(
        "FLOAT_SERIAL_NO",
        "PLATFORM_NUMBER",
        "PLATFORM_TYPE",
        "DEPLOYMENT_CRUISE_ID",
        "DEPLOYMENT_PLATFORM",
        "LAUNCH_DATE",
        "status",
        "last_report",
        "next_report",
        "days_since_last",
        "last_cycle",
        age=F("age_cal")
    )
    
    # 最后只需要处理age的天数转换,几乎没有额外开销
    res = []
    for dep in deployments:
        dep["age"] = dep["age"].days
        res.append(dep)
    
  • 给查询条件加联合索引
    打开Django的数据库查询日志确认执行计划,给过滤用到的HISTORICAL和LAUNCH_DATE字段加联合索引,可以进一步降低数据库层的查询耗时:

    class deployment(models.Model):
        # 你的其他字段定义
        class Meta:
            indexes = [
                models.Index(fields=["HISTORICAL", "LAUNCH_DATE"]),
            ]
    

    加完后执行python manage.py makemigrations和python manage.py migrate同步索引即可。

优化完成后可以用django-debug-toolbar确认实际执行的SQL数量,正常场景下这个接口只会触发1次数据库查询,不会再有额外的隐式查询。

内容的提问来源于stack exchange,提问作者R. Anderson

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 16:57:20