Django REST Framework Serialize非常慢

时间:2014-11-14 17:37:22

标签: json django serialization django-rest-framework django-queryset

我使用django-restframework在Python 2.7和Django 1.7.1中 我有一个API,它返回一些从数据库中获取的特定值,它使用像这样的自定义序列化器:

class InventarioSerializer(serializers.ModelSerializer):
    item = serializers.RelatedField(source='producto.item')
    ubicacion = serializers.RelatedField(source='ubicacion.nombre')
    class Meta:
        model = Inventario
        fields = ('epc','item','cantidad','ubicacion')

我的API视图以这种方式调用:

class ItemEnInventarioViewSet(InventarioListModelMixin, viewsets.ModelViewSet):
    serializer_class = InventarioSerializer
    renderer_classes = (UnicodeJSONRenderer,)

我的ListModelMixin是这样的:

class InventarioListModelMixin(object):
    def list(self, request, *args, **kwargs):
        item = request.QUERY_PARAMS.get('item', None)
        inventario = Inventario.objects.filter(producto__item = item)
        if inventario.count() == 0:
            return HttpResponse(u"El item %s no se encuentra en el inventario" % item,status=400)
        self.object_list = inventario
        # Switch between paginated or standard style responses
        page = self.paginate_queryset(self.object_list)
        if page is not None:
            serializer = self.get_pagination_serializer(page)
        else:
            serializer = self.get_serializer(self.object_list, many=True) <<--THIS IS THE PROBLEM
        return Response(serializer.data)

它工作正常,但当我尝试从数据库获取1000个或更多条目时,序列化器使它非常慢, 25到35秒。

对DB的查询非常简单,因此DB根本不是问题。

如果我使用此函数序列化查询集&#34; data = serializers.serialize('json', myQuerySet)&#34;它需要最多3秒但我没有得到我想要的信息,这就是我使用自定义序列化器的原因

是否有最快的方式来获取这些数量的值?也许与另一个Serializer?任何想法?

**答案谢谢Kevin ** 将查询更改为:

inventario = Inventario.objects.select_related('producto__item','ubicacion__nombre').filter(producto__item = item)

...使序列化程序不会在每个结果行中命中数据库以检索外来值。

2 个答案:

答案 0 :(得分:11)

  

对DB的查询非常简单,因此DB根本不是问题。

确保您的查询没有N+1 issue。它们可能很简单,但如果它们很多,那么它将花费相当多的时间。我在这里写了很多关于fixing performance issues in Django REST Framework的文章,你可以通过搜索找到很多关于它的信息。

  

是否有最快的方式来获取这些数量的价值?也许与另一个Serializer?任何想法?

如果您的数据不经常更改,或者您可以处理任何可能的缓存问题,那么您可以通过向API添加一些缓存来获益。 drf-extensions提供了许多有用的缓存,可以帮助您解决问题。

  

当我尝试从数据库中获取1000个或更多条目时

我知道你的代码内置了分页,但我想在处理大量数据时强调使用分页的价值。请求中的性能往往是非常线性的,您需要检索的数据越多,检索它的时间就越长。

答案 1 :(得分:7)

对我来说,N + 1数据库查询并没有成为答案。花了一个下午的分析精确定位,但在这样做后,答案结果令人沮丧地在我的序列化程序中有几个DecimalField字段。

我的用例很简单:3000-4000个实例需要序列化。所有select_related优化都已执行,但我仍然看到2-3秒的序列化时间,而不是我期待的.5-1.5秒。经过几个小时的试验和错误(评论/取消注释字段)后,当我对所有DecimalField进行注释时,我看到了运行时的大幅下降(50%)。

对我来说,解决方案是将我的DecimalField更改为FloatField。当然,你这样做的代价是精度损失,但对我来说这很好。