Opened 11 years ago
Closed 11 years ago
#23440 closed Cleanup/optimization (invalid)
select_related with multiple ForeignKey to same table generates sub-optimal SQL
| Reported by: | djbug | Owned by: | nobody |
|---|---|---|---|
| Component: | Uncategorized | Version: | 1.6 |
| Severity: | Normal | Keywords: | select_related |
| Cc: | Triage Stage: | Unreviewed | |
| Has patch: | no | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description (last modified by )
I have this model where Relation has 2 foreign keys, both to Node.
class Node(models.Model):
name = models.CharField(max_length=25)
class Relation(models.Model):
left = models.ForeignKey(Node)
right = models.ForeignKey(Node, related_name='right')
I've shown a sample query along with the SQL that's generated by Django:
Relation.objects.select_related().filter(id=1)
SELECT "relation"."id", "relation"."left_id", "relation"."right_id", "left"."id", "left"."name", T3."id", T3."name", FROM "relation" INNER JOIN "left" ON ( "relation"."left_id" = "left"."id" ) INNER JOIN "right" T3 ON ("relation"."right_id" = T3."id" ) WHERE "relation"."id" = 1
There are 2 INNER JOIN happening above. However we can do with just 1 INNER JOIN, since left & right are pointing to the same table. See below:
SELECT "relation"."id", "relation"."left_id", "relation"."right_id", "left"."id", "left"."name", FROM "relation" INNER JOIN "left" ON ( "relation"."left_id" = "left"."id" OR "relation"."right_id" = "left"."id") WHERE "relation"."id" = 1
P.S. Not sure if this is related : [7125]
Change History (2)
comment:1 by , 11 years ago
| Description: | modified (diff) |
|---|
comment:2 by , 11 years ago
| Resolution: | → invalid |
|---|---|
| Status: | new → closed |
Note:
See TracTickets
for help on using tickets.
I don't think that actually works. Assume the following on node table:
And relation has one model with left_id = 1 and right_id = 2. Now, the second query produces results
Which is not the wanted result. Instead we want all the related objects in a single row. Trying to collapse the two rows into a single object while iterating leads to all sorts of really complex issues which we are not going to tackle.