Bob's Blog

Web开发、测试框架、自动化平台、APP开发、机器学习等

返回上页首页

Django Restframework性能优化的选择



在用DRF做后端开发时,在数据量一增多后就会发现api的返回实在是慢,装了django-debug-toolbar来检查行为表现以确定瓶颈时,有如下发现:

1. DB Query时间正常,但是有重复的单个sql比如分别以id来查询多次,于是多出来的查询会增加时间。

2. ModelSerializer是真的慢。在view中的queryset是惰性计算,并不会实际操作,而在serializer序列化数据时,则发现执行了比较多的sql查询,因为在重写to_representation时取了外键的数据。

因此可以通过如下变化来优化后端性能表现:

1. 除非需要,尽量不要增加nested_serializer。比如Book里有Author这个外键,但是不一定需要把AuthorSerializer的数据也展示出来,这样会造成额外的sql。在没有额外要求下,只序列化当前model里的数据。比如这里面的:https://www.django-rest-framework.org/api-guide/relations/#nested-relationships

2. 当有需要序列化foreignkey或者manytomany的字段的数据时,考虑使用prefetch_related和select_related来优化sql查询。比如如果不用这两种,实际情况是取了一个Publisher,但是又额外执行了多次取通过publisher_id来取book的sql。这篇是不错的说明:http://ses4j.github.io/2015/11/23/optimizing-slow-django-rest-framework-performance/

select_realted可用于OneToOneFiled, ForeignKey字段,相当于sql中使用INNER JOIN,这样可以把publisher表和book表联合起来查询一次,避免多余sql查询,避免多个多余的以id查询的sql;

prefetch_related可用于ManyToManyField, OneToManyField(即ForeignKey的反向查询),它优化的方式是把以id分别查询的sql放在一起变成了id in (1, 2, 3)这种,也避免了多余sql查询。

3. 当业务逻辑和数据模型确实没有可优化的地方了,还可以用缓存。可参考https://www.django-rest-framework.org/api-guide/caching/

比如可以用下面的方式:

from django.utils.decorators import method_decorator
from django.views.decorators.cache import cache_page
from django.views.decorators.vary import vary_on_cookie


class AuthorDetail(generics.RetrieveUpdateAPIView):

    queryset = Author.objects.all()
    serializer_class = AuthorSerializer

    @method_decorator(cache_page(60 * 60 * 2))   # Cache requested url for each user for 2 hours
    @method_decorator(vary_on_cookie)
    def get(self, request, *args, **kwargs):
        return super().get(request, *args, **kwargs)

 

下一篇:  Android快速录制视频并转为gif动图
上一篇:  cProfile检查python程序的性能表现和可视化结果

共有0条评论

添加评论

暂无评论