1

How can I optimize my api View or Serializer ? It takes more than 3 minutes to perform the task. I think it due to foreign key fields but even I retrieve them on the serializer fields, it still run slowly.

api/View.py

@api_view(['GET', 'POST'])
def edge_list(request):
    """
    List all edges of all networks, or create a new edge.
    """
    if request.method == 'GET':
        edges = Edge.objects.all()
        context = {'request': request}  # for filtering by field in url
        serializer = EdgeSerializer(edges, many=True, context=context)
        return Response(serializer.data)

    elif request.method == 'POST':
        serializer = EdgeSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.error, status=status.HTTP_400_BAD_REQUEST)

api/serializers.py

class EdgeSerializer(DynamicFieldsMixin, serializers.ModelSerializer):

    class Meta:
        model = Edge
        fields = (
            'id', 'edge_id', 'name', 'length', 'speed',
            'lanes', 'param1', 'param2', 'param3', 'network',
            'road_type', 'source', 'target'
            )

api/models.py

class Edge(models.Model):
    network = models.ForeignKey(RoadNetwork, on_delete=models.CASCADE)
    source = models.ForeignKey(Node, related_name='source',
                               on_delete=models.CASCADE,
                               help_text='Source node of the edge',
                               )
    target = models.ForeignKey(Node, related_name='target',
                               on_delete=models.CASCADE,
                               help_text='Target node of the edge',
                               )
    road_type = models.ForeignKey(RoadType, on_delete=models.CASCADE,
                                  help_text='Roadtype of the edge'
                                  )
    edge_id = models.PositiveBigIntegerField(db_index=True)
    name = models.CharField(max_length=80, blank=True, help_text='Name of the edge')
    geometry = models.LineStringField()
    length = models.FloatField()
    speed = models.FloatField(null=True, blank=True)
    lanes = models.SmallIntegerField(null=True, blank=True)
    param1 = models.FloatField(null=True, blank=True)
    param2 = models.FloatField(null=True, blank=True)
    param3 = models.FloatField(null=True, blank=True)

    def __str__(self):
        return self.name or 'Edge {}'.format(self.edge_id)

1 Answer 1

3

Yep, you're doing N*3+1 queries.

Instead of

edges = Edge.objects.all()

try

edges = Edge.objects.select_related('network', 'source', 'target').all()

to fetch all of those foreign key fields in one query.

You can also try

edges = Edge.objects.prefetch_related('network', 'source', 'target').all()

for three queries (with possibly less redundant data).

Sign up to request clarification or add additional context in comments.

2 Comments

thanks. I tried this but it didn't change nothing. It is still very slow.
@aba2s Then break out a profiler. My best next guess is that JSON serialization takes some time.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.