【问题标题】:Django rest framework ModelSerializer runs too slowlyDjango rest 框架 ModelSerializer 运行太慢
【发布时间】:2016-05-03 01:51:31
【问题描述】:

我们想为我们的 django 项目提供一个 api,所以我们使用 drf(django rest 框架)。 我们使用 ModelSerializer,它提供了一个快捷方式,可以让您自动创建一个带有与 Model 字段对应的字段的 Serializer 类。 我们的问题是它运行得很慢。换句话说,序列化过程大约需要 40 秒才能检索到响应。

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

class MyObjViewSet(viewsets.ModelViewSet):

    pagination_class = LargeResultsSetPagination

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

    serializer_class = MyObjSerializer

我的对象模型

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 秒!

【问题讨论】:

标签: django performance django-rest-framework


【解决方案1】:

其实是drf的真正问​​题。
如果您有很多由查询集返回的对象,那么您必须执行几个步骤:
1.检查你是否使用many=True,它将产生显着的性能提升。
2. 避免在大型对象集上使用ModelSerializer。事实上,值得考虑的是避免任何形式的rest_framework.Serializer
3.尝试使用serpy库进行序列化。但你不应该忘记它与rest_framework.Serializer 不完全兼容。
4. 使用.values()DictSerializer。它将大大加快序列化速度。
5. 不要忘记数据库中的索引。 6.在使用ForeignKey时使用prefetch_relatedselect_related等强大的东西。
7.最后一种方式是使用简单的dict。否则,我没有得到明显的结果:只有 10% 与 serpyDictSerializer

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

我希望,drf 的开发人员会在框架上做一些性能改进。

【讨论】:

    【解决方案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')
    

    【讨论】:

    • 谢谢,我做到了,但问题仍然存在!
    • 看看这个stackoverflow.com/questions/26109184/…关于迁移但正如你所说的查询时间看起来很正常所以我没有线索
    • 查询时间正常!我想我的问题与 DRF 逻辑有关,而不是与数据库逻辑有关。但我找不到解决方案。我的意思是查找和检索查询集的过程很重要...
    【解决方案3】:

    伙计,不要使用“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:littler or equal then

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

    5、range:时间范围

    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、day:一天

    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可以让你的requset更快,你只需要在得到这些数据后进行排序。

    【讨论】:

      猜你喜欢
      • 2015-05-15
      • 2013-10-05
      • 2019-03-24
      • 1970-01-01
      • 2012-10-25
      • 1970-01-01
      • 2016-06-01
      • 2022-01-25
      • 1970-01-01
      相关资源
      最近更新 更多