Django каркас отдыха крайне медленный (рекурсивные отношения) - PullRequest
0 голосов
/ 01 февраля 2019

Для моего проекта я начал использовать Laravel для API, а не переключился на Django / django rest framework, я сделал это для увеличения скорости, поскольку мне нужно запрашивать большие данные.

Теперь я получил следующееСитуация: у меня есть «Группа», в которой есть «Предметы» и рекурсивная связь.

Теперь в группе может быть около 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)

Я протестировал тот же запрос с API-интерфейсом Laravel и он намного быстрее, все еще заметно медленный, но все в порядке (5-10 секунд).С каркасом отдыха django он слишком медленный (1 минута +/-), и это всего лишь страница с 1 группой из 2500 предметов.

Я знаю, что занимает много времени, класс RecursiveField, потому что, когда я удаляю этозапрос выполняется менее чем за 2 секунды.Итак, мой вопрос в чем основная причина, потому что это создает рекурсивное отношение (я сомневаюсь)?Или это потому, что я не получаю предварительную выборку?

И, конечно, какой лучший способ сделать это?

Спасибо

Ответы [ 2 ]

0 голосов
/ 01 февраля 2019

Проблема не в DRF, а в самой структуре данных.

Очень медленно django рекурсивно запрашивает всех предков / потомков, вам следует использовать более эффективную структуру данных.

По той же причине, по которой я написал django-treenode, она выполняет операции с деревом без запроса к БД.Вы можете прочитать документы здесь: https://github.com/fabiocaccamo/django-treenode

0 голосов
/ 01 февраля 2019

У вас есть несколько вариантов, но я не думаю, что они хороши.Рекурсивные запросы не очень хорошо поддерживаются в Django.

  1. Переработайте модель данных, чтобы избежать необходимости использовать рекурсию для извлечения объектов из базы данных.Вы можете добавить root ForeignKey к Subject on Subject, который бы идентифицировал корневой субъект.Это позволит вам довольно легко захватить все предметы на дереве.Затем вам нужно будет расположить их в своем View / Viewset, чтобы они соответствовали порядку (если это необходимо).
  2. Используйте raw() и рекурсивную функциональность вашей базы данных для извлечения моделей.Это потребует необработанного SQL и может быть болезненным для поддержки.
  3. Использование django_cte.Я использовал это в одном из своих проектов для нескольких запросов, но я не большой поклонник этого.Это нарушает некоторые функции при вызове update() в пустом наборе запросов.Тем не менее, это будет работать и не потребует от вас перехода на сырой SQL.
...