Search code examples
mysqldjangodjango-modelsquery-optimization

Is it faster to follow relations in a query parameter or using model attribute lookup in Django Models?


Say I have three Django Models:

  • User,
  • Staff which is one-to-one with User,
  • Thing which is many-to-one with Staff on the 'owner' field.

Using a MySQL database, which of these performs better?

Thing.objects.filter(owner=user.staff)  # A
Thing.objects.filter(owner__user=user)  # B

What about if I am checking that the Thing that I want is owned by a User:

try:
    Thing.objects.get(id=some_id, owner=user.staff)  # D
    Thing.objects.get(id=some_id, owner__user=user)  # E
except Thing.DoesNotExist:
    return None
else:
    pass # do stuff

# Or F:
thing = Thing.objects.get(id=some_id)
if thing.owner.user != user:
    return None
pass # do stuff

Solution

  • It very much depends on how you got the original objects and what you've done with them since. If you've already accessed user.staff, or you originally queried User with select_related, then the first query is better as it is a simple SELECT on one table, whereas the second will do a JOIN to get to the User table.

    However, if you have not already accessed user.staff and did not originally get it via select_related, the first expression will cause user.staff to be evaluated, which triggers a separate query, before even doing the Thing lookup. So in this case the second query will be preferable, since a single query with a JOIN is better than two simple queries.

    Note however that this is almost certainly a micro-optimization and will have very little impact on your overall run time.