Badly affecting performance in populating ManyToMa

2019-07-29 16:17发布

问题:

As I'm using django rest framework for building my product api.

Here is my model in models.py

class Tag(models.Model):
    tag = models.CharField(max_length=10, unique=True)

class Product(models.Model):
    product_name = models.CharField(max_length=100)
    tag = models.ManyToManyField(Tag, blank=True, default=None, related_name='product_tag')

serializers.py :

class TagSerializer(serializers.ModelSerializer):
    class Meta:
        model = Tag
        fields = '__all__'

class ProductSerializer(serializers.HyperlinkedModelSerializer):
    tag = TagSerializer(many=True, read_only=True)

    class Meta:
        model = Product
        fields = '__all__'

views.py :

class ProductViewSet(viewsets.ModelViewSet):
    queryset = Product.objects.all()
    serializer_class = ProductSerializer

I have given the url for ProductViewset, so when I hit the api it gives me the results as well but it takes too much time to load, it takes around 2 minutes to give me the response.

I'm having 2000 product objects in database which needs to be populated.

When I exclude the 'tag' field in "ProductSerializer", response comes very fast with all 2000 records.

Please suggest where is the loophole, why its affecting performance so much especially when I add this ManyToMany field.

回答1:

I always use django-debug-toolbar to debug my queryset to find bottleneck/duplicate query in my project. Django orm always using lazy load to retrieve related fields from database. You can change this default behavior of your queryset by eager load your many to many field using prefetch_related.

class ProductViewSet(viewsets.ModelViewSet):
    queryset = Product.objects.prefetch_related('tag').all()
    serializer_class = ProductSerializer

Reference: prefetch_related