Sql 优化DRF序列化

Sql 优化DRF序列化,sql,python-3.x,django,django-rest-framework,Sql,Python 3.x,Django,Django Rest Framework,我面临一个问题,我必须优化ORM对象的序列化。我有一个对象,比如说Foo,我有一个巨大的序列化程序。我提到了很多领域,比如 class FooSerializer(ModelSerializer): bar = serializers.StringRelatedField(source="bar") apple = serializers.StringRelatedField(source="bar.food") cat = ser

我面临一个问题,我必须优化ORM对象的序列化。我有一个对象,比如说
Foo
,我有一个巨大的序列化程序。我提到了很多领域,比如

class FooSerializer(ModelSerializer):
    bar = serializers.StringRelatedField(source="bar")
    apple = serializers.StringRelatedField(source="bar.food")
    cat = serializers.StringRelatedField(source="bar.animals.pet")
    ball = serializers.StringRelatedField(source="bar.toy")
    # a lot of other complex fields related with Foo
    # direct-indirect, 1-1 or 1-M relations
    class Meta:
        model = Foo
        fields = ['bar', 'apple', 'cat', 'ball', ....]

现在,这导致序列化需要花费很多时间。我添加了日志记录,并看到许多SQL查询被执行。这些查询重复了很多次。根据我在文档中的理解,尽管Django QuerySet是延迟执行的,但DRF中的序列化是查询每个字段以填充。请详细说明序列化字段是如何在较低级别填充的,这将对我有更多帮助

我想在这里实现的是尽可能少地进行查询。在上面的示例中,要获取
bar.food
bar.toy
我只想执行一个查询,该查询将获取
bar
对象,并且我可以访问
food
toy
对象

我能想到的一个可能的解决方案是评估所有相关对象并在上下文中传递它们。也就是说,计算
bar
对象并将其作为上下文发送。然后,我的
apple
字段将填充为
SerializerMethodField
中的
self.context['bar'].food
。你能建议一个更好的方法吗?可能是批处理吗

假设: 序列化的数据是热的,我们无法缓存它

编辑: 对于每次序列化,当前正在执行的SQL查询是两位数的

编辑(根据Daneil的要求进行查询)


亲爱的NIkhil请尝试使用预回迁选择和选择相关

然后,主查询集和所有指定的相关对象的结果缓存将完全加载到内存中。这改变了QuerySet的典型行为,QuerySet通常试图避免在需要之前将所有对象加载到内存中,即使在数据库中执行查询之后也是如此。
更详细的信息

你也可以添加你的查询吗?@daneilJames我不能添加所有的查询,因为有很多查询。我有一个实例,当查询总数达到250+时。我正在添加一个有问题的示例查询。所有查询都是自动生成的。我无法
预回迁
选择\u related
,因为我提到的查询正在执行以填充字段。如果我在调用序列化程序之前获取
bar
对象,序列化程序会再次查询DB以获取
bar
对象吗?基本上,序列化程序是获取输入并给出响应的一种方式,所以所有内容都保留在查询中,因为您说您有250个查询,每个查询都必须涉及某些表。所以,您必须首先优化查询。如果我是您,我会从视图端发送您在序列化程序中使用的所有源代码,而不在序列化程序中提供源代码。“每个查询都必须涉及某些表。因此,您必须先优化查询。”这对我来说很有意义。我将尝试在一个大查询中提取所有字段并进行相应的序列化。尝试创建一个提供整个上下文的查询,并在不实际访问数据库表的情况下向其内部逻辑移动,而使用存储的变量保留整个上下文查询
SELECT `app_foo`.`id`, `app_foo`.`field_1`, (many app_foo fields),
`app_foo`.`created_at`, `app_foo`.`updated_at` FROM `app_foo` INNER JOIN
`app_bar` ON `app_foo`.`id` = `app_bar`.`id` WHERE `app_foo`.`id` = 12; args(12,)