Difference in foreign key lookup through object.fk.id and object.fk_id

Viewed 201

I have not found this question on SO.

Is there a speed difference between the following two variants of doing foreign key lookup in django's object model? I only need the foreign key.

class A(models.Model):
    x = models.PositiveIntegerField(null=True)

class B(models.Model):
    a = models.ForeignKey(A, null=True, on_delete=models.CASCADE)
    y = models.PositiveIntegerField(null=True)

b = b.objects.last()

Which is faster or are they the same?

b.a_id
b.a.id

edit: Actually I think I can answer it myself... the second variant should be slower since it creates the whole object from the db, right?

2 Answers

Simply: yes, there is a definite difference, and b.a_id is faster than b.a.id.

The latter retrieves the entire a object from the database as an additional query. (You can save that query by adding .select_related('a'), but doing .a.id instead of .a_id is still unnecessary.)

Is there a speed difference between the following two variants of doing foreign key lookup in django's object model? I only need the foreign key.

Yes the fk_id is stored in the database. By default (that is if you do not .defer(..) that field, one way or another), it is loaded when the query is materialized (for example the object is loaded).

.fk_id this does not require extra querying. Whereas .fk is, unless you load it through .select_related(..) or .prefetch_related(..), will require extra querying. Relations (like a foreign key relation) are loaded lazily: if you query self.fk.id, you will first fetch .fk resulting in an extra query, and then you will fetch the .id from that object (which takes no extra queries).

Related