Django - 大序列化器和小序列化器之间的时间差异

Django - difference in time between big serializer and small

我正在创建一个音乐评级应用程序,我正在使用 REST Framework 在 Django 中创建 API。这非常简单,但我想知道使用大型序列化器模型和小型序列化器时加载时间是否有很大差异。 我所说的大和小是指获取更多数据。例如我有一个专辑页面,我需要在其中使用这个序列化程序。

"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

这个序列化程序相当庞大,我只需要专辑详细信息页面的数据。我还在专辑列表页面中提取了这些数据,我列出了我所有的专辑,几乎所有这些数据都没有被使用。 如果我制作另一个序列化器,稍微简单一点,并在专辑列表页面中使用它,加载速度会有很大的不同吗?

如果是这样,我可以创建一个 Viewset,在我访问我的 /albums api url 时可以看到不太复杂的序列化程序,而在我访问时显示更复杂的序列化程序更具体 url 比如 /albums/1?

由于您关心加载对象的速度,还有另一种提高性能的方法。 我们可以使用多种方法

  • ModelSerializer(较慢)
  • 只读 ModelSerializer(比 ModelSerializer 快一点)
  • 常规序列化器只读
  • 常规序列化程序(比 ModelSerializer 快近 60%)

因为在可写的ModelSerializer中,很多时间花在了验证上。所以我们可以通过将所有字段标记为 read-only.

来使其更快

Python 中写了很多关于序列化性能的文章。正如预期的那样,大多数文章都侧重于使用 select_related 和 prefetch_related 等技术改进数据库访问。虽然这两种方法都是改善 API 请求的整体响应时间的有效方法,但它们并未解决序列化本身的问题。

是的,你应该使用多个序列化器而不是一个大嵌套序列化器

视情况而定。通常,使用只有 frontend/users 需要的数据来限制响应是一个好习惯。当然,发生的情况是这些需求将在您的前端视图和页面中演变。克服这个问题的一种方法是为不同的视图或查询参数提供不同的序列化程序,例如使用 get_serializer_class method on your viewset' 或在序列化程序本身中使用请求对象。另外,如果我没记错的话,有一个扩展允许你定义一些你想要或不想要的字段。

DRF 序列化程序不仅在执行序列化程序 'purely speaking',因为您可以重新定义字段,您可以有方法字段,显然还有 relantionfield。

大多数时候,对于 IntegerField、CharFields 等字段,序列化大量数据不会有问题,因为它很简单。但是对于 RelatedFields (foreignkey, ManyToMany ...),如果您不预取它们,这可能会导致一些问题:关系和嵌套关系将为您的所有项目创建一个新的数据库查询。

例如,在您的示例中,您有专辑和曲目。如果您在获取专辑之前不预取曲目,您将在查询中为每个专辑创建一个请求!这是因为序列化程序会尝试序列化每个字段,当它看到 track 字段时,Django 会从数据库中获取对象。这样做会很明显,并且根本不会扩展,即使数据集很小。

另一种处理这些问题的方法是分页,虽然它有时仍然很慢,但它允许您只提供数据库的一个子集,因此只有有限的项目可以序列化。

总结一下:取决于你序列化的内容,通常会因为没有预取数据或方法字段而变慢。尽可能多地使用分页,是的,如果您知道它的数据会更少(因此在线上的数据更快 response/less),您可以使用不同的序列化器。

注意:在处理您不想拥有大量序列化程序的非常复杂的对象时,您可以使用 GraphQL,用户知道他想要什么并向后端询问这些字段。