我们想为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秒!
答案 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.使用DictSerializer
和prefetch_related
。它将大大提高您的序列化速度。
5.不要忘记数据库中的索引。
6.与select_related
一起使用时,请使用ForeignKey
和dict
之类的功能强大的东西。
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并查看数据库查询时间。它会帮助你找出时间的位置。