How to increase performance of a serializer method

Hi,

I’m trying to improve performance of some API’s…
I already defined select_related and prefetch_related in queryset, but still very slow!

read this article and realize that serializer could be the problem!

I’m using DRF, ModelViewSet and ModelSerializer for the most cases. Also, I tried to setup

  • UserModelSerializer
  • UserReadOnlyModelSerializer
  • UserSerializer
  • UserReadOnlySerializer

but none of them seems to have any effect.
there is another thing that I should try?
To implement somenthing like the serializer_user function, should I rewrite my ViewSet for an APIViewSet or something more generic?

as an example, my user table has about 12k register and it takes about 17 seconds to send a response:

Number of Queries : 10
Finished in : 16.95s

Please post the model, serializers and view related to your question.

1 Like

UserModel

class User(models.Model):

    class UserGenders(models.TextChoices):
        FEMALE = constants.FEMALE
        MALE = constants.MALE
        NOT_INFORMED = constants.NOT_INFORMED

    first_name = models.CharField()
    last_name = models.CharField()
    email = models.EmailField(
        verbose_name=constants.EMAIL_ADDRESS,
        blank=True,
        null=True,
        unique=True
    )
    phone_number = PhoneNumberField(null=True, blank=True
    )
    gender = models.CharField(max_length=50, choices=UserGenders.choices)
    birth_date = models.DateField(blank=True, null=True)
    corporate_name = models.CharField(max_length=100, blank=True)
    trading_name = models.CharField(max_length=100, blank=True)
    is_staff = models.BooleanField(default=False)
    is_active = models.BooleanField(default=True)
    nickname = models.CharField(max_length=255, blank=True)
    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['first_name', 'last_name']

    class Meta:
        verbose_name_plural = "Users"

    def __str__(self):
        return str(self.email)

ViewSet

class UserViewSet(viewsets.ModelViewSet):
    queryset = acc_models.User.objects.all()
    http_method_names = ['get', 'post', 'put', 'patch', 'head', 'options', 'delete']
    permission_classes = (isAdmin, )

    def get_serializer_class(self):
        return acc_serializers.UserGETSerializer
        # return acc_serializers.UserReadOnlyGETSerializer
        # return acc_serializers.UserToRepresentationGETSerializer

ModelSerializer (original ~19 seconds)

class UserGETSerializer(serializers.ModelSerializer):
    class Meta:
        model = acc_models.User
        exclude = []

ReadOnlySerializer (test #1 ~17 seconds)

class UserReadOnlyGETSerializer(serializers.ModelSerializer):

    class Meta:
        model = acc_models.User
        fields = (
            'first_name', 'last_name', 'email', 'phone_number', 'gender', 'birth_date',
            'corporate_name', 'trading_name', 'is_staff', 'is_active', 'nickname',
        )
        read_only_fields = fields

ToRepresentationSerializer (test #2 ~ 8 seconds)

class UserToRepresentationGETSerializer(serializers.BaseSerializer):
    def to_representation(self, instance):
        result = {
            "id": instance.id,
            "first_name": instance.first_name,
            "last_name": instance.last_name,
            "email": instance.email,
            "phone_number": str(instance.phone_number1),
            "gender": instance.gender,
            "birth_date": instance.birth_date,
            "corporate_name": instance.corporate_name,
            "trading_name": instance.trading_name,
            'is_staff':  instance.is_staff,
            'is_active':  instance.is_active,
            "nickname": instance.nickname,
        }
        return result

It seems that your problem is with the database query.
Since the serializers is only getting the data from one table, there is no way of optmizing with prefetch_related or select_related.

Are you using django-debug-toolbar? This can help you visualize how many queries are being issued, and the times to make them. If so, go to your browser on the url of this API route to see these metrics.
If not, you may need to do some explain on the query in your database.