Django休息框架ModelSerializer运行得太慢

时间:2016-01-26 13:26:22

标签: django performance django-rest-framework

我们想为django项目提供api,所以我们使用drf(django rest framework)。 我们使用ModelSerializer,它提供了一个快捷方式,允许您自动创建一个Serializer类,其中包含与Model字段对应的字段。 我们的问题是它运行得非常慢。换句话说,序列化过程大约需要40秒,直到检索到响应。

我们如何才能减少这种延迟? VIEW

class MyObjViewSet(viewsets.ModelViewSet):

    pagination_class = LargeResultsSetPagination

    def get_queryset(self):
        queryset = MyObj.objects.all().order_by('time')
        return queryset

    serializer_class = MyObjSerializer

我的Obj模型

class MyObj(models.Model):
    id = models.BigIntegerField(primary_key=True)
    time = models.DateTimeField()
    type = models.CharField(max_length=5)
    user = models.ForeignKey('User', related_name='myobj')

MyObj用户模型

class User(models.Model):
    id = models.IntegerField(primary_key=True)
    username = models.CharField(max_length=80)

我的Obj序列化程序

class MyObjSerializer(serializers.ModelSerializer):

    class Meta:
        model = MyObj
        fields = ('id', 'type', 'time', 'user')

我的问题是当我想要检索我的obj列表时,它需要大约40秒!

4 个答案:

答案 0 :(得分:2)

这不是序列化程序的问题,而是查询中的问题。

你得到了所有的物品,我认为因为分页而有很多物品,你也希望它们都按时间排序。问题是模型定义没有提示数据库在时间字段上创建索引。

尝试添加提示以在数据库中创建索引,速度将会提高。

  class MyObj(models.Model):
      id = models.BigIntegerField(primary_key=True)
      time = models.DateTimeField(db_index=True)
      type = models.CharField(max_length=5)
      user = models.ForeignKey('User', related_name='myobj')

答案 1 :(得分:1)

从本质上讲,这是drf的真实问题。
如果queryset返回了很多对象,则必须执行一些步骤:
 1.检查您是否使用ModelSerializer,它将显着提高性能。
 2.避免在大型对象集上使用rest_framework.Serializer。实际上,值得考虑的是避免使用任何serpy
 3.尝试使用rest_framework.Serializer库进行序列化。但您不要忘记它与.values()并不完全兼容。
 4.使用DictSerializerprefetch_related。它将大大提高您的序列化速度。
 5.不要忘记数据库中的索引。  6.与select_related一起使用时,请使用ForeignKeydict之类的功能强大的东西。
 7.最后一种方法是使用简单的serpy。否则,我不会得到可观的结果:与DictSerializer和{{1}}相比,只有10%的结果。

我遇到一种情况,当我必须序列化许多对象(大约3-5k)时,drf序列化程序的开销至少为2.5秒(没有sql的时间)。优化后,我得到了大约200-300毫秒。

我希望drf的开发人员可以在框架上进行一些性能改进。

答案 2 :(得分:1)

伙计,不要使用“ MyObj.objects.all()。order_by('time')”,

如果您拥有数以百计的数据,那么只需按时间获取所有数据并进行排序, 这将花费很长时间……

“这不是序列化程序的问题,这是订单问题。” 您可以限制搜索时间,请使用:

1,gt:然后更大

now = datetime.datetime.now()
#yesterday
start = now – datetime.timedelta(hours=23, minutes=59, seconds=59)
a=yourobject.objects .filter(youdatetimcolumn__gt=start)

2,gte:则更大或更等于

a=yourobject.objects .filter(youdatetimcolumn__gte=start)

3,lt:然后是

a=yourobject.objects .filter(youdatetimcolumn__lt=start)

4,lte:等于或等于

a=yourobject.objects .filter(youdatetimcolumn__lte=start)

5,范围:时间范围

start_date = datetime.date(2005, 1, 1)
end_date = datetime.date(2005, 3, 31)
Entry.objects.filter(pub_date__range=(start_date, end_date))

6,年份:年份之一

Entry.objects.filter(pub_date__year=2005)

7,月:一个月

Entry.objects.filter(pub_date__month=12)

8,天:一天

Entry.objects.filter(pub_date__day=3)

9,week_day:一个工作日

Entry.objects.filter(pub_date__week_day=2)

来源:https://www.cnblogs.com/linjiqin/p/3821914.html

如果需要使用get.all,则只需不使用“ order_by_time”,在正常情况下,不使用order_by_time可使您的请求集更快,只需在获取这些数据后对其进行排序。

答案 3 :(得分:0)

这在很大程度上取决于您的列表大小,数据库配置/调优和查询优化。

安装Django Debug Toolbar并查看数据库查询时间。它会帮助你找出时间的位置。