DRF序列化关于嵌套序列化消耗性能问题的解决

DRF序列化关于嵌套序列化极其消耗性能问题的解决

DRF序列化给我们提供了一个很方便的序列化与反序列化的方法,但是如果在序列化器中使用嵌套,会极其消耗性能。

class Qctestroombeta(BaseModel):

    id = models.CharField(primary_key=True, max_length=36)
    name=models.CharField(max_length=64, verbose_name='考场名称')


class Qctestroom(BaseModel):

    id = models.CharField(primary_key=True, max_length=36)
    name = models.CharField(max_length=64, verbose_name='考场名称')
    beta = models.ForeignKey(Qctestroombeta,on_delete=models.CASCADE,null=True,blank=True,verbose_name='模拟考场',related_name='testroom')

上面是两个简单的外键模型

class roomnamebetaSerializers(serializers.ModelSerializer):
    name = serializers.CharField(source='beta.name')
    class Meta:
        model = Qctestroom
        fields = ( 'id','name',)

这里的序列化会涉及到外键,我们可以很方便的写出这样的嵌套查询,但是Django在执行查询的时候,会查很多次表,这里的name我们查询的是外键beta的一个字段name。
当第一个用户的数据进行序列化的时候,DRF需要查询一次Qctestroombeta表
第二个用户的数据进行序列化的时候,DRF又需要查询一次Qctestroombeta表
…………

这样的一个序列化器执行一次可能会耗时非常多的时间

django给了我们两个方法来解决这个问题
select_related()
在对QuerySet使用select_related()函数后,Django会获取相应外键对应的对象,从而在之后需要的时候不必再查询数据库了。这种方法我们称为预加载。

tl = Qctestlevel.objects.filter(testroom_id=id,strike=False)
tl = Qctestlevel.objects.select_related().filter(testroom_id=id,strike=False)

这里的select_related里面可以有参数,即你要保存使用的外键类似select_related(beta__name)

select_related() 接受可变长参数,每个参数是需要获取的外键(父表的内容)的字段名,以及外键的外键的字段名、外键的外键的外键…。若要选择外键的外键需要使用两个下划线“__”来连接。
如果有多个要保存的外键,则要使用多个select_related拼接起来

depth
select_related() 接受depth参数,depth参数可以确定select_related的深度。Django会递归遍历指定深度内的所有的OneToOneField和ForeignKey.

tr = Qctestroom.objects.select_related(depth = d).all()

prefetch_related()
多用于多对多和一对多,与select_related不同的是select_related用的是join语句进行查询,如果表太多,则会使join得到的表很长,导致sql语句的性能变低,而prefetch_related是分别查询每张表,然后再分别处理他们之间的关系。
与select_related用法类似。

上一篇:Django之DB数据库优化


下一篇:Java related——Navicat安装教程