【问题标题】:Django rest framework db query slowDjango rest框架数据库查询慢
【发布时间】:2015-10-10 13:03:18
【问题描述】:
  • 我有一个带有 16 个 DecimalFields 的 Django 模型。
  • 我创建了一个 ListAPIView 来获取这个数据。
  • 有大约 5000 个此模型的实例 在我的数据库中,对此 api 视图的 GET 请求超过 15 秒。

型号:

class MyModel(models.Model):
    f1 = models.DecimalField (max_digits=8, decimal_places=3)
    f2 = models.DecimalField (max_digits=8, decimal_places=3)
    f3 = models.DecimalField (max_digits=8, decimal_places=3)
    f4 = models.DecimalField (max_digits=8, decimal_places=3)
    f5 = models.DecimalField (max_digits=8, decimal_places=3)
    f6 = models.DecimalField (max_digits=8, decimal_places=3)
    f7 = models.DecimalField (max_digits=8, decimal_places=3)
    f8 = models.DecimalField (max_digits=8, decimal_places=3)
    f9 = models.DecimalField (max_digits=8, decimal_places=3)
    f10 = models.DecimalField (max_digits=8, decimal_places=3)
    f11 = models.DecimalField (max_digits=8, decimal_places=3)
    f12 = models.DecimalField (max_digits=8, decimal_places=3)
    f13 = models.DecimalField (max_digits=8, decimal_places=3)
    f14 = models.DecimalField (max_digits=8, decimal_places=3)
    f15 = models.DecimalField (max_digits=8, decimal_places=3)
    f16 = models.DecimalField (max_digits=8, decimal_places=3)

序列化器:

class MyModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = MyModel

我没有对数据进行任何过滤。当我在 django shell 中运行查询时,它会在几毫秒内运行。我认为序列化是这里的问题。但是,我使用的是默认的 ModelSerializer。

所有这些字段都在同一个表中,所以我看不出这里怎么会有 N+1 问题。

我可以做些什么来进一步分析这个问题?对于这么多模型实例,我是否应该期望我的查询会这么慢?

【问题讨论】:

  • 你想把所有的 5000 个值带到客户端吗?如果不分页并仅序列化所需的项目。
  • 我们现在只能盲目猜测。给我们一些眼睛,给我们模型和序列化器。
  • @ArunGhosh 我确实想将所有 5000 个值带到客户端。由于这些数据只有 1mb 左右,似乎应该有一种方法可以在 15 秒内从数据库到达客户端。
  • @KevinBrown 真的吗?我认为我对模型和序列化程序的描述足够直截了当,但我已经更新了问题。
  • @rawbeans 那是……令人担忧的。通常非查询问题是因为自定义模型和序列化程序对数据进行额外处理。但是,如果您的序列化程序和模型是裸露的(如您的示例所示),您将需要拿出一个实际的 Python 分析器。

标签: django serialization query-optimization django-rest-framework django-queryset


【解决方案1】:

不要使用ListAPIView,而是尝试使用ModelViewSet

为自己创建一个只继承ListModelMixin的自定义视图

class ListModelViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
    pass

现在将其扩展到您的视图集并在那里写下您的queryset

def get_queryset(self):
    Model.objects.all()

这不是一个可以加快速度的逻辑,因为最终它们都继承了相同的东西,但值得一试。

如果这也不起作用...另一个可能的原因可能是 5000 个对象是一个相当大的数字。 Shell 不会一次返回所有对象。它执行对 Model.objects.all() 的查询,但将对象的数量限制为 20,然后是这个 ....(剩余元素被截断)......,所以我想这与 web 视图相比减少了时间当它必须带入列表中的所有元素时。

【讨论】:

    【解决方案2】:

    安装django-toolbar 并查看查询时间和CPU 时间。如果查询需要时间并且正在执行一些延迟加载,请检查 prefetch_relatedselect_related

    【讨论】:

    • 查询时间90ms,CPU时间26000ms。另外,我不确定 prefetch_related 和 select_related 在这里如何有用,因为所有字段都在同一个表中
    【解决方案3】:

    这是因为有序列化器,你可以使用Model.objects.values()而不是使用序列化器来提高性能,这将很快返回相同的数据。

    【讨论】:

    • 我将查询集从 Model.objects.all() 更改为 Model.objects.values(),但查询仍然很慢。
    猜你喜欢
    • 2022-01-25
    • 2014-12-22
    • 1970-01-01
    • 1970-01-01
    • 2012-10-25
    • 1970-01-01
    • 2021-08-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多