0

Simply put, what is the order of performance and speed among the following similar looking queries in the Django ORM?

.filter(a).filter(b)

instances = Model.objects.filter(a=A).filter(b=B)

Q objects

instances = Model.objects.filter(Q(a=A) & Q(b=B))

or/and queries

instances = Model.objects.filter(a=A) & Model.objects.filter(b=B)

keyword queries

instances = Model.objects.filter(a=A, b=B)

AND please don't copy and paste chatgpt or any other ai services. Thank you, and please leave any comments below.

NotTheDr01ds
  • 15,620
  • 5
  • 44
  • 70
coderDcoder
  • 585
  • 3
  • 16
  • 3
    One filter with multiple constraints does not necessarily yield the same results as multiple filters with one constraint each. Please read https://stackoverflow.com/a/5542966/6890912 – blhsing Aug 28 '23 at 09:50

2 Answers2

3

Since Django querysets are lazy, there won't be any DB calls until you try to get data from it (e.g. list(instances)).
So if you created queryset and then added few more .filter's, it will perform the same as if you created it at once.
If you don't use Q explicitly - Django uses it under the hood so there is no difference here as well.

In fact you can do print(str(instances.query)) to see final query prepared by Django, and in our case all 4 queries are the same, so
There is no difference in performance and speed at all.

Bohdan
  • 424
  • 1
  • 4
  • 15
1

The first aspect here is whether the these all produce per se the same query, and the same results. That is not the case for all queries.

Let us begin with two lines that will produce the same query:

instances = Model.objects.filter(Q(a=A) & Q(b=B))
instances = Model.objects.filter(a=A, b=B)

Indeed, both are equivalent, since the .filter(..) will construct a Q object based on what you pass. So both end up with a query:

SELECT *
FROM model
WHERE a = a AND b = b

so the exact query. Constructing the query with the ORM is only a matter of some text-processing that is resolved in microseconds, so that will not have much impact on the performance.

It is however a different story if you compare Model.objects.filter(a=A, b=B) and Model.objects.filter(a=A).filter(b=B) if a and b work with the same model. Indeed, the two consecutive .filter(…) calls [Django-doc] will make separate joins, not work with the single one. This thus means that the semantics is different, you thus should not look at the performance but what your query is supposed to do, what items it should retrieve.

The same happens with Model.objects.filter(a=A) & Model.objects.filter(b=B), here you thus make two queries you eventually intersect, but if the a and b are the same, it does not work like a .filter(a=A, b=B).

Django does not do the filtering, it just constructs an SQL query to do that, and the database will then process the query. You thus should focus on what you aim to select, less how it is done.

Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555