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

Django外键关联序列化查询耗时90秒性能问题排查求助

问题根因

你遇到的是典型的Django ORM N+1查询问题:

  • 未序列化外键详情时,仅需查询1次Cost表即可拿到所有数据,耗时300-400ms
  • 嵌套序列化外键后,默认惰性查询的ORM会为每条Cost记录单独触发5次数据库查询(查employee、job1~job4关联记录),如果返回1万条Cost记录,就会触发5万次额外查询,耗时自然飙升到数十秒。
解决方案

仅需1行代码修改即可解决性能问题:在视图的queryset中使用select_related预加载所有关联外键,一次性将Cost表和关联的员工、工作项数据全部查出,避免重复查询。

如果不需要嵌套的返回结构,还可以简化序列化器配置,直接返回字段值而非嵌套对象。

代码示例

1. 保留原嵌套返回结构(性能优化版)

仅修改视图的queryset即可,序列化器无需改动:

class JoinedFilterCostList(generics.ListAPIView):
    # 预加载所有关联外键,消除N+1查询
    queryset = Cost.objects.select_related('employee', 'job1', 'job2', 'job3', 'job4').all()
    serializer_class = CostModelSerializer
    filter_backends = [DjangoFilterBackend]
    filterset_class = CostListFilter

修改后查询耗时会回到300-500ms区间,和未关联外键时的性能基本一致。

2. 简化为扁平返回结构(可选)

如果不需要嵌套的对象结构,直接返回字段值,可以修改序列化器,无需额外嵌套序列化器:

class CostModelSerializer(serializers.ModelSerializer):
    employee = serializers.CharField(source='employee.employee_name')
    job1 = serializers.CharField(source='job1.No')
    job2 = serializers.CharField(source='job2.No')
    job3 = serializers.CharField(source='job3.No')
    job4 = serializers.CharField(source='job4.No')

    class Meta:
        model = Cost
        fields = '__all__'

返回结果示例:

{
    "id": 12,
    "employee": "Person 1",
    "job1": "30201",
    "job2": "N/A",
    "job3": "N/A",
    "job4": "N/A",
    "hours1": 10,
    "hours2": 0,
    "hours3": 0,
    "hours4": 0,
    "date": "2021-07-12"
}
关于to_field参数返回null的说明

to_field是外键定义阶段的参数,用于指定关联表的关联字段(默认关联主键ID),你在序列化阶段使用该参数自然无法拿到正确值,返回null属于预期结果,序列化阶段取关联字段值请使用source参数即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 04:09:05