Django rest框架非常慢(递归关系)

时间:2019-01-31 23:59:18

标签: django django-rest-framework

对于我的项目,我开始将Laravel用于api而不是切换到Django / django rest框架,这样做是为了提高查询大数据的速度。

现在我遇到以下情况: 我得到了一个具有“主题”并且具有递归关系的“组”。

现在,一个小组可以拥有2000多个科目(包括后代科目),而父级科目可以拥有+/- 30个科目。

这是我的代码:

序列化器

class RecursiveField(serializers.Serializer):
    def to_representation(self, value):
        serializer = self.parent.parent.__class__(value, context=self.context)
        return serializer.data

class SubjectSerializer(serializers.ModelSerializer):
    parent_of = RecursiveField(many=True, read_only=True)

    class Meta:
        model = Subject
        fields = ("id", "name", "parent_of", "parent")

class GroupSerializer(serializers.ModelSerializer):
    subjects = SubjectSerializer(many=True, read_only=True)

    class Meta:
        model = Group
        fields = ("id", "name", "subjects")

    def setup_eager_loading(cls, queryset):
        return queryset.prefetch_related("subjects")

观看次数

class GroupViewSet(ModelViewSet):

    class Paginator(BasePaginator):
        model = Group

    queryset = Group.objects.all()
    serializer_class = serializers.GroupSerializer
    pagination_class = Paginator

    def get_queryset(self):
        return self.get_serializer().setup_eager_loading(GroupViewSet.queryset)

我使用laravel api测试了相同的请求,它的速度更快,但仍然很慢,但是还可以(5-10秒)。使用django rest框架时,速度太慢(大约1分钟+/-),而这仅仅是一个包含2500个主题的小组的页面。

我知道RecursiveField类花了很长时间,因为当我删除该查询时,不到2秒即可完成。所以我的问题是最主要的原因,因为它创建了一个递归关系(我怀疑)?还是因为我不预取?

当然,什么是最好的方法?

谢谢

2 个答案:

答案 0 :(得分:0)

您有几种选择,但是我认为没有什么很棒。 Django对递归查询的支持不是很好。

  1. 重新设计数据模型,以防止需要使用递归从数据库中获取主题。您可以在主题上的主题上添加一个root ForeignKey来标识根主题。这将使您相当容易地抓住树上的所有主题。然后,您必须将它们安排在您的“视图/视图集”中以适应顺序(如果需要)。
  2. 使用raw()和数据库的递归功能来获取模型。这将需要原始SQL,并且可能难以维护。
  3. 使用django_cte。我已经在我的一个项目中使用过此功能进行了一些查询,但是我并不喜欢它。在空查询集上调用update()会破坏某些功能。但是,它将起作用,并且不需要您使用原始SQL。

答案 1 :(得分:0)

问题不是DRF,而是数据结构本身。

django中以递归方式查询所有祖先/后代的速度非常慢,您应该使用更有效的数据结构。

出于与我编写django-treenode相同的原因,它执行树操作而不查询数据库。 您可以在此处阅读文档:https://github.com/fabiocaccamo/django-treenode