#31792 closed Cleanup/optimization (fixed)
Use `EXISTS(SELECT 1 ...)` for subqueries
| Reported by: | w0rp | Owned by: | Simon Charette |
|---|---|---|---|
| Component: | Database layer (models, ORM) | Version: | dev |
| Severity: | Normal | Keywords: | |
| Cc: | Triage Stage: | Ready for checkin | |
| Has patch: | yes | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
If you write a QuerySet call like so in Django...
MyModel.objects.all().exists()
the query run will be like so.
SELECT 1 AS "a" FROM "myapp_mymodel" LIMIT 1;
If you use the Exists() function to filter with a subquery like so...
MyModel.objects.filter(Exists(MyOtherModel.objects.all()))
The subquery will be run like so.
... WHERE EXISTS(SELECT "myapp_myothermodel"."id", ... FROM "myapp_myothermodel");
It would be nice if the queries generated for Exists() used SELECT 1 like .exists() does, where possible. In an app I work on, I have one query in particular that is 15KB in size, but only around 8KB if I apply .annotate(_1=Value(1, output_field=IntegerField())).values_list('_1') to all of the subqueries. That change alone is enough to make my queries much easier to debug.
Change History (7)
comment:1 by , 5 years ago
| Triage Stage: | Unreviewed → Accepted |
|---|---|
| Type: | Uncategorized → Cleanup/optimization |
comment:2 by , 5 years ago
| Component: | Uncategorized → Database layer (models, ORM) |
|---|
comment:3 by , 5 years ago
| Owner: | set to |
|---|---|
| Status: | new → assigned |
comment:5 by , 5 years ago
| Triage Stage: | Accepted → Ready for checkin |
|---|---|
| Version: | 3.0 → master |
I could swear there was another ticket about that but I cannot find it.
The logic to clear the column is a bit more complex than what you've described here but it's all detailed in
Query.has_results(link) andSQLCompiler.has_results(link) so it could be added toExists.as_sql.Ideally the logic would be encapsulated in a
Querymethod so it doesn't have to be duplicated inQuery.has_resultsandExists.as_sqlso both could path could benefit from optimizations such as #24296.