Django - разница во времени между большим сериализатором и маленьким

Я создаю приложение для рейтинга музыки и использую REST Framework для создания API в Django. Это очень просто, но мне интересно, есть ли большая разница во времени загрузки при использовании больших сериализаторов модели и маленьких. Под большими и маленькими я подразумеваю получение большего количества данных. Например, у меня есть страница альбома, где мне нужно использовать этот сериализатор.

"id": 2,
"title": "OK Computer",
"slug": "ok-computer",
"created_at": "2022-02-22T21:51:52.528148Z",
"artist": {
    "id": 13,
    "name": "Radiohead",
    "slug": "radiohead",
    "image": "http://127.0.0.1:8000/media/artist/images/radiohead.jpg",
    "background_image": "http://127.0.0.1:8000/media/artist/bg_images/radiohead.jpg",
    "created_at": "2022-02-22T00:00:00Z"
},
"art_cover": "http://127.0.0.1:8000/media/album/art_covers/ok-computer_cd5Vv6U.jpg",
"genres": [
    "Alternative Rock",
    "Art Rock"
],
"overall_score": null,
"number_of_ratings": 0,
"release_date": "1997-05-28",
"release_type": "LP",
"tracks": [
    {
        "position": 1,
        "title": "Airbag",
        "duration": "00:04:47"
    },
    {
        "position": 2,
        "title": "Paranoid Android",
        "duration": "00:06:27"
    }
],
"links": [
    {
        "service_name": "spotify",
        "url": "https://open.spotify.com/album/6dVIqQ8qmQ5GBnJ9shOYGE?si=L_VNH3HeSMmGBqfiqKiGWA"
    }
],
"aoty": null

Этот сериализатор довольно массивный, и мне нужны эти данные только для страницы Albums details. Я также использую эти данные на странице списка альбомов, где я перечисляю все свои альбомы, и почти все эти данные не используются. Если я сделаю другой сериализатор, немного менее сложный, и использую его на странице списка альбомов, будет ли резкая разница в скорости загрузки?

И если да, то могу ли я сделать Viewset, в котором менее сложный сериализатор будет виден, когда я обращаюсь к api url /albums, а более сложный сериализатор будет отображаться, когда я обращаюсь к более определенному url, например /albums/1?

Поскольку вас беспокоит скорость загрузки объектов, есть еще один способ повысить производительность. Например, есть несколько методов, которые мы можем использовать

  • ModelSerializer (медленнее)
  • Read Only ModelSerializer (Немного быстрее ModelSerializer)
  • Регулярный сериализатор Только чтение
  • Регулярный Сериализатор (почти на 60% быстрее, чем ModelSerializer)

Потому что в записываемом ModelSerializer много времени уходит на валидацию. Поэтому мы можем сделать это быстрее, пометив все поля как доступные только для чтения.

О производительности сериализации в Python было написано много статей. Как и ожидалось, большинство статей посвящено улучшению доступа к БД с помощью таких техник, как select_related и prefetch_related. Хотя оба эти способа являются действенными для улучшения общего времени ответа на запрос API, они не рассматривают саму сериализацию.

И да, вы должны использовать несколько сериализаторов, а не БОЛЬШОЕ гнездо одного

Все зависит от ситуации. Обычно хорошей практикой является ограничение ответа данными, которые нужны только фронтенду/пользователям. Конечно, случается так, что эти потребности будут меняться в зависимости от ваших представлений и страниц на фронтенде. Один из способов преодолеть это - предоставить разные сериализаторы для разных представлений или параметров запроса, используя, например, get_serializer_class method on your viewset' или в самом сериализаторе с объектом запроса. Также, если я правильно помню, есть расширение, которое позволяет вам определить некоторые поля, которые вы хотите возвращать или нет.

Сериализатор DRF - это не только сериализатор "чисто говоря", потому что вы можете переопределять поля, у вас могут быть поля метода и, очевидно, relantionfield.

В большинстве случаев для таких полей, как IntegerField, CharFields и т.д., у вас не будет проблем с сериализацией большого количества данных, потому что это просто. Но с RelatedFields (foreignkey, ManyToMany ...) это может вызвать некоторые проблемы, если вы не сделаете их предварительную выборку: отношения и вложенные отношения создадут новый запрос к базе данных для всех ваших элементов.

Например, в вашем примере у вас есть альбом и треки. Если вы не сделаете предварительную выборку треков перед выборкой альбома, вы создадите запрос для каждого альбома в вашем запросе! Это происходит потому, что сериализатор будет пытаться сериализовать каждое поле, и когда он увидит поле track, Django возьмет объект из базы данных. Это будет заметно, и не будет масштабироваться даже при небольшом наборе данных.

Другой способ решить эти проблемы - сделать пагинацию, хотя она все еще иногда будет медленной, она позволяет вам предоставлять только подмножество вашей базы данных, и таким образом иметь только ограниченное количество элементов для сериализации.

Подведем итоги: зависит от того, что вы сериализуете, обычно это будет медленно из-за отсутствия предварительной выборки данных или из-за полей метода. Старайтесь использовать пагинацию как можно чаще, и да, вы можете использовать другой сериализатор, если знаете, что в нем будет намного меньше данных (и, следовательно, более быстрый ответ/меньше данных на проводе).

Примечание: при работе с действительно сложными объектами, где вы не хотите иметь большое количество сериализаторов, вы можете использовать GraphQL, где пользователь знает, что он хочет, и спрашивает бэкенд об этих полях.

Вернуться на верх