7

tôi bằng Python 2.7 và Django 1.7.1 với django-restframework Tôi đã một API trả về cho tôi một số giá trị cụ thể được thực hiện fron cơ sở dữ liệu, nó sử dụng một Serializer Tuỳ chỉnh như thế này:Django REST của Khung Serialize cực kỳ chậm

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') 

xem API của tôi được gọi theo cách này:

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

và ListModelMixin của tôi là thế này:

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) 

Nó hoạt động tốt, nhưng khi tôi cố gắng để GET hình thành DB arround 1000 hoặc nhiều mục, serializer làm cho nó rất rất chậm, arround 25-35 giây.

Truy vấn đến DB rất đơn giản nên DB không phải là vấn đề gì cả.

Nếu tôi sắp đặt từng queryset với chức năng này "data = serializers.serialize('json', myQuerySet)" phải mất ít nhất 3 giây nhưng tôi không nhận được các thông tin như tôi muốn, đó là lý do tại sao tôi sử dụng một Tuỳ chỉnh Serializer

Có cách nào nhanh nhất để GET số lượng giá trị đó? Có thể với Serializer khác? bất kỳ ý tưởng?

** ĐÁP Nhờ Kevin ** Thay đổi truy vấn để:

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

... làm cho Serializer không để đạt các cơ sở dữ liệu mỗi kết quả hàng để lấy các giá trị ngoại.

+1

trông giống như một vấn đề truy vấn ... – Raphael

+0

Truy vấn của tôi rất đơn giản, nó tìm 8 trường với một INNER JOIN và một WHERE, cơ sở dữ liệu trả về dữ liệu trong vòng chưa đến 0,25 giây, vì vậy chắc chắn không phải là truy vấn hoặc db –

Trả lời

9

Truy vấn DB rất đơn giản nên DB không phải là vấn đề gì cả.

Đảm bảo bạn không có N+1 issue với truy vấn của mình. Họ có thể đơn giản, nhưng nếu có nhiều người trong số họ sau đó nó sẽ mất một số lượng đáng kể thời gian. Tôi đã viết khá một chút về fixing performance issues in Django REST Framework ở đây và bạn có thể tìm thấy rất nhiều về nó bằng cách tìm kiếm xung quanh.

Có cách nào nhanh nhất để NHẬN số lượng giá trị đó không? Có thể với Serializer khác? bất kỳ ý tưởng?

Nếu dữ liệu của bạn không thay đổi thường xuyên hoặc bạn có thể giải quyết mọi vấn đề về bộ nhớ đệm, bạn có thể hưởng lợi đáng kể khi thêm một số bộ nhớ đệm vào API của mình. drf-extensions cung cấp một số mixin hữu ích cho bộ nhớ đệm có thể giúp bạn nếu vấn đề của bạn không thực sự với các truy vấn của bạn.

khi tôi cố gắng GET tạo DB arround 1000 hoặc nhiều mục

Tôi hiểu rằng mã của bạn đã pagination xây dựng vào nó, nhưng tôi muốn nhấn mạnh giá trị trong sử dụng pagination khi làm việc với số lượng lớn dữ liệu. Hiệu suất trong các yêu cầu có xu hướng rất tuyến tính, và càng có nhiều dữ liệu bạn phải truy xuất càng lâu thì nó sẽ lấy lại tất cả.

+1

Tôi thực hiện truy vấn trực tiếp trong DB (mssql) và mất ít hơn 0,25 giây để cung cấp cho tôi các giá trị, dữ liệu của tôi đang thay đổi nhiều lần trong một ngày, vì vậy, bộ nhớ đệm không phải là cách tốt nhất, bởi vì tôi có thể lấy dữ liệu được lưu trong bộ nhớ cache một hoặc hai lần, và sau đó nó lại thay đổi. Việc phân trang âm thanh tốt nhưng trong mã của tôi 'trang' luôn luôn là Không có vì vậy' get_pagination_serializer' là không bao giờ xúc động, làm thế nào tôi có thể làm cho pagination? là nó nhanh hơn? –

+0

Nếu bạn đang thực hiện truy vấn chính ('Blah.objects.all()') thì bạn thiếu các truy vấn bổ sung cần thiết cho các mối quan hệ. Bởi vì bạn đang sử dụng 'producto' và' ubicacion', nên cần có các truy vấn bổ sung cho những thứ đó. Vì vậy, nếu bạn đang nhận được một đối tượng, ba truy vấn cần phải được thực hiện. Nếu mỗi truy vấn mất 100ms, đó là 300ms. Nếu bạn đang nhận được 100 đối tượng, đó là 10 giây trong các truy vấn một mình. Điều này được gọi là một vấn đề truy vấn N + 1, và tôi chắc chắn sẽ tìm kiếm nó (và đọc các câu trả lời được liên kết). –

+0

Khung công tác Django REST có tính năng phân trang được xây dựng trong: http://www.django-rest-framework.org/api-guide/pagination –

7

Đối với tôi, truy vấn cơ sở dữ liệu N + 1 không phải là câu trả lời. Phải mất một buổi chiều của hồ sơ để xác định, nhưng sau khi làm như vậy câu trả lời bật ra được, bực bội, một vài lĩnh vực DecimalField trong serializer của tôi.

Trường hợp sử dụng của tôi rất đơn giản: 3000-4000 trường hợp cần được sắp xếp theo thứ tự. Tất cả các tối ưu hóa select_related đã được thực hiện, tuy nhiên tôi vẫn thấy 2-3 giây thời gian tuần tự hóa chứ không phải là .5-1.5 giây mà tôi mong đợi. Sau một vài giờ dùng thử và lỗi (bình luận ra/bỏ ghi chú của các trường), tôi thấy một sự sụt giảm rất lớn (50%) trong thời gian chạy khi tôi có tất cả nhận xét của DecimalField.

Giải pháp, đối với tôi, là thay đổi DecimalField thành FloatField. Tất nhiên bạn làm điều này với chi phí mất chính xác, nhưng vì mục đích của tôi là tốt.

+0

Tôi không thể tìm thấy bất cứ điều gì khác cho thấy lý do tại sao DecimalField sẽ rất chậm (tôi biết điều này là hai năm trước đây). Bên cạnh việc thay đổi định nghĩa mô hình trường, có một giải pháp khác không? – JohnO

Các vấn đề liên quan