django - 优化 Django Rest ORM 查询

标签 django performance django-models django-rest-framework query-performance

我是一个 React 前端,django 后端(用作 REST 后端)。 我继承了该应用程序,它使用许多模型和序列化加载所有用户数据。它加载速度非常慢。 它使用过滤器来查询单个成员,然后将其传递给序列化器:

found_account = Accounts.objects.get(id='customer_id')
AccountDetailsSerializer(member, context={'request': request}).data

然后有很多各种各样的嵌套序列化器:

AccountDetailsSerializers(serializers.ModelSerializer):
   Invoices = InvoiceSerializer(many=True)
   Orders = OrderSerializer(many=True)
   ....

从日志来看,ORM 似乎发出了如此多的查询,这太疯狂了,对于某些端点,我们最终得到了 50 - 60 个查询。

  1. 我应该尝试使用 select_lated 和 prefetch,还是跳过所有这些,只尝试编写一个 sql 查询来执行多个联接并以 json 形式一次性获取所有数据?

  2. 当我传入单个对象(get 的结果)而不是查询集到序列化器时,如何定义预取/select_lated?

  3. 某些数据库实体之间没有链接,这意味着不是 fk 或多对关系,只是保存一个具有另一个 id 的字段,但数据库中并未强制执行该关系?这对我来说会是一个问题吗?这是否意味着我应该再次跳过 select_lated 方法并编写客户 sql 来获取?

  4. 您建议如何解决这个噩梦般的查询的性能调整?

最佳答案

我建议首先看看使用 prefetch_lated 会产生什么效果。它会对加载时间产生重大影响,并且实现起来相当简单。按照上面的例子,这样的事情就可以显着减少加载时间:

AccountDetailsSerializers(serializers.ModelSerializer):

    class Meta:
        model = AccountDetails
        fields = (
            'invoices',
            'orders',
        )

    invoices = serializers.SerializerMethodField()
    orders = serializers.SerializerMethodField()

    def get_invoices(self, obj):
        qs = obj.invoices.all()\
            .prefetch_related('invoice_sub_object_1')\
            .prefetch_related('invoice_sub_object_2')
        return InvoiceSerializer(qs, many=True, read_only=True).data

    def get_orders(self, obj):
        qs = obj.orders.all()\
            .prefetch_related('orders_sub_object_1')\
            .prefetch_related('orders_sub_object_2')
        return OrderSerializer(qs, many=True, read_only=True).data 

至于您的架构问题,我认为还有很多其他因素会影响您是否应该重构代码库以及重构代码库的程度。但总的来说,如果您使用了 Django 和 DRF,如果您能够接受这些框架的惯用语和模式,而不是尝试通过自己的修复来接受它们,那么您将获得更好的开发人员体验。

关于django - 优化 Django Rest ORM 查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55326865/

相关文章:

MySQL InnoDB 大表的 INSERT 性能

javascript - Jquery - 使用多个选择器或每个选择器更有效

python - Django 属性错误 : 'Alias' object has no attribute 'urls'

python - 如何为现成的数据库制作 django 管理面板?

python - 如何使用 Python 从 MongoDB 中的此文档中删除值

c# - 为什么 Directory.GetFiles() 在后续运行中运行得更快?

django - Django 模型自动字段的初始值

python - Django:使用用户作为外键保存表单

django - select_related 字段的调用管理器

python - 如何使用 celery 在 Django 上设置周期性任务?