繁体   English   中英

Django 序列化程序查询时间过长

[英]Django Serializer takes too much time to query

我有一个 API,目前只返回 465 KB 数据,但处理时间太长:

这是 postman 的图像:

在此处输入图像描述

查询中只有 300 个对象,视图和序列化程序如下所示:

视图.py

class MaterialRequestListEmployeeAPIView(generics.ListAPIView):
    serializer_class = EMaterialRequestListSerializer
    permission_classes = (permissions.IsAuthenticated,)
    queryset = MaterialRequest.objects.all().order_by('-id')

    def get_queryset(self):
        queryset = super(MaterialRequestListEmployeeAPIView, self).get_queryset()
        return queryset

序列化器.py

class EMaterialRequestFlowsListSerializer(serializers.ModelSerializer):

    class Meta:
        model = MaterialRequestFlow
        fields = "__all__"
        depth = 1


class EMaterialRequestListSerializer(serializers.ModelSerializer):

    flows = EMaterialRequestFlowsListSerializer(many=True)

    class Meta:
        model = MaterialRequest
        fields = "__all__"
        depth = 1

模型.py

class MaterialRequestFlow(models.Model):

    flow = models.ForeignKey(Flow, on_delete=models.CASCADE)
    kit = models.ForeignKey(Kit, on_delete=models.CASCADE)
    quantity = models.IntegerField(default=0)


class MaterialRequest(models.Model):

    owner = models.ForeignKey(User, on_delete=models.CASCADE, related_name='owner')
    flows = models.ManyToManyField(MaterialRequestFlow)
    is_allocated = models.BooleanField(default=False)
    delivery_required_on = models.DateTimeField(default=datetime.now)
    raised_by = models.CharField(max_length=1000, default="__________", blank=True, null=True)

如何提高 API 的性能? 我尝试增加 AWS 上的instance配置,但它对检索时间没有影响

尝试分析代码并确定瓶颈所在可能很有用。 但是给你一些建议:

  1. 避免对字段使用“ all ”,您可能会得到不需要的数据并且序列化速度很慢(取决于数据是什么)
  2. 避免使用 depth=1... 这本质上是上述的扩展,因为我们不知道它对您的相关模型集实际做了什么。 我已经使用 DRF 多年,但从未使用过深度,更喜欢指定应使用哪些序列化器序列化哪些模型
  3. 尽可能使用 prefetch_related 和 select_related

在这种情况下,我将从以下内容开始:

  • 将 MaterialRequestListEmployeeAPIView 的查询集变量更改为MaterialRequestListEmployeeAPIView MaterialRequest.objects.all().order_by('-id').prefetch_related('materialrequestflow_set') (或您为该反向关系设置的任何别名
  • 将 EMaterialRequestListSerializer 上的字段更改为 `('id', 'flows')
  • 将 EMaterialRequestFlowsListSerializer 上的字段更改为('id', 'quantity')
  • (摆脱视图上的get_queryset方法,因为它不执行父 class 尚未执行的任何操作 - 可选,显然不会影响性能)

第一个,取决于你的数据,会产生最大的影响,所以请先单独尝试一下。

如果那不好,则进行所有提到的更改,如果它仍然很慢,那么您似乎遇到了某种数据库问题。 如果速度很快,则返回以包含更多字段(例如“EMaterialRequestFlowsListSerializer”上的“kit”)并尝试找到瓶颈。

如果您的 model 中存在任何外键,那么您需要使用 select / prefetch 相关选项在单个数据库命中中调用它们,否则它们将为您的 model object 中的每个外键调用数据库。

在您的情况下,请在视图集中将您的查询集修改为:

MaterialRequest.objects.select_related(
    'owner'
).prefetch_related(
    'flows'
).all().order_by('-id')

您可以在https://docs.djangoproject.com/en/3.2/topics/performance/阅读更多内容

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM