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, где пользователь знает, что он хочет, и спрашивает бэкенд об этих полях.