【问题标题】:Speeding up Django Rest Framework Model Serializer N+1 Query problem加速Django Rest Framework Model Serializer N+1 Query问题
【发布时间】:2023-04-03 11:51:01
【问题描述】:

我有一个序列化Order 模型的 DRF ModelSerializer 类。这个序列化器有一个字段:

num_modelA = serializers.SerializerMethodField() `

def get_num_modelA(self, o):
    r = ModelA.objects.filter(modelB__modelC__order=o).count()

    return r

ModelA 有一个ForeignKey 字段modelB,ModelB 有一个ForeignKey 字段modelC,ModelC 有一个ForeignKey 字段order

问题显然在于,对于每个序列化的订单,它都会对数据库进行额外的查询,这会降低性能。

我已经实现了一个静态方法setup_eager_loading,如here 所述,它修复了我拥有的其他字段的 N+1 查询问题。

@staticmethod
def setup_eager_loading(queryset):
    # select_related for "to-one" relationships
    queryset = queryset.select_related('modelD','modelE')
    
    return queryset

我的想法是我也可以使用prefetch_related 来减少查询次数。但我不确定如何执行此操作,因为 Order 和 ModelA 由多个外键分隔。让我知道是否有任何其他信息有用

【问题讨论】:

  • 可以分享模型吗?尤其是ForeignKeys 和related_name=s 很重要。

标签: django api serialization django-rest-framework


【解决方案1】:

您可以使用注释:

from django.db.models import Count

# …

@staticmethod
def setup_eager_loading(queryset):
    # select_related for "to-one" relationships
    return queryset.select_related('modelD','modelE').annotate(
        num_modelA=Count('modelC__modelB__modelA')
    )

在您的Order 的序列化程序中,您可以使用num_modelA 作为IntegerField

from rest_framework import serializers

class OrderSerializer(serializers.ModelSerializer):
    num_modelA = serializers.IntegerField()

    class Meta:
        model = Order
        fields = ['num_modelA', 'and', 'other', 'fields']

【讨论】:

  • 谢谢,这很有帮助。我现在想知道是否需要计算 modelA 的数量,其中 modelB.is_active == True 我将如何去做这样的事情。
  • @fictionalPlant:你可以使用Count('modelC__modelB__modelA', filter=Q(modelC__modelB__is_active=True))
  • 我将.annotate() 添加到setup_eager_loading 方法中,它能够减少正在执行的查询数量,但它最终实际上增加了api响应的总时间
  • @fictionalPlant:查询还有其他 N+1 问题吗?
  • 有,我已经解决了似乎可以用select_relatedprefetch_related 方法解决的问题。剩下的问题需要使用类似的注释方法,但我尝试通过注释解决的每一个问题都会显着增加响应时间。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-10-05
  • 1970-01-01
  • 2014-05-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-07
相关资源
最近更新 更多