On Saturday, July 5, 2014 12:42:39 AM UTC+3, Jon Dufresne wrote:
>
> Suppose I have the following models:
>
> ---
> class Container(models.Model):
> pass
>
> class Item(models.Model):
> container = models.ForeignKey(Container)
> previous = models.ForeignKey('self', null=True)
> current = models.BooleanField()
> flag = models.BooleanField()
> ---
>
> Item represents a chain of items, all grouped by a container (like a
> linked list). The field "current" represents the most recent item
> (front of the list). The field "flag" is simply something to query on.
>
> Suppose I perform the following query:
>
> ---
> Item.objects.filter(current=True,
> container__item__previous__isnull=True, container__item__flag=True)
> ---
>
> That is, I'm looking for all current items such that the first item in
> the chain has flag = true. Django 1.6 produces the following SQL for
> this query:
>
> ---
> SELECT ...
> FROM "myapp_item"
> INNER JOIN "myapp_container"
> ON ( "myapp_item"."container_id" = "myapp_container"."id" )
> LEFT OUTER JOIN "myapp_item" T3
> ON ( "myapp_container"."id" = T3."container_id" )
> WHERE ("myapp_item"."current" = True AND T3."previous_id" IS NULL AND
> T3."flag" = True )
> ---
>
> The OUTER JOIN is the problem. Why is this not a more efficient INNER
> JOIN? This query is very inefficient as the the database gets larger.
> This causes slow downs on pages.
>
This have been fixed in 1.7. Pre-1.7 there was no join "demotion". That is,
when the ORM generated a LEFT JOIN expression it was never changed back to
INNER JOIN. Here the container__item__previous__isnull=True generates LEFT
JOIN for the item join.
In 1.7 there exists some new code to do join demotion. In this case it
works because container__item__flag=True can produce results only when the
item join produces results => the query never produces results with LEFT
JOIN of item => the existing LEFT JOIN for alias T3 can be "demoted" to
INNER JOIN.
Interestingly, if I try this on 1.7, this query is apparently not even
> supported. I get the following error:
>
I wasn't able to reproduce this - are you sure the query is exactly the
same both on 1.6 and 1.7? Are models are set up correctly before generating
the query? If after double-checking you still get the error, could you post
a sample project somewhere?
- Anssi
--
You received this message because you are subscribed to the Google Groups
"Django developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/django-developers.
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-developers/d9253e4a-df9c-4e75-bc5a-3f883a62db0f%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.