Django Queryset:等效过滤子句的效率

时间:2013-12-15 12:46:11

标签: python django filter django-queryset

为什么在一个过滤子句中应用多个参数并不等同于为每个参数多次调用过滤器?

我有博客评论模型。

对此查询的评估需要几分钟时间:

Blog.objects.filter(comment__created__gt=from).filter(comment__created__lt=till)

虽然这个评估时间少于一秒:

Blog.objects.filter(comment__created__gt=from, comment__created__lt=till)

更新我的models.py:

class Blog(models.Model):
    pass

class Comment(models.Model):
    blog = models.ForeignKey('Blog')
    created = models.DateTimeField(auto_now_add=True)

我使用Django 1.4.5。

1 个答案:

答案 0 :(得分:1)

好吧,让我们看看每个查询的sql:

对于此示例,我仅使用now = till = from_dt = datetime.now()作为示例。此外,从不使用变量名称。如果你感到惊讶或问为什么然后停止你正在做的一切,并开始学习基本的python。无论如何:

In [6]: query1 = Blog.objects.filter(comment__created__gt=from_dt).filter(comment__created__lt=till)

In [7]: print query1.query
SELECT "myapp_blog"."id", "myapp_blog"."name" 
FROM "myapp_blog" 

    INNER JOIN "myapp_comment" 
    ON ("myapp_blog"."id" = "myapp_comment"."blog_id") 

    INNER JOIN "myapp_comment" T3 
    ON ("myapp_blog"."id" = T3."blog_id") 

WHERE ("myapp_comment"."created" > 2013-12-15 15:54:50.633000  
AND T3."created" < 2013-12-15 15:54:50.633000 )

好好看看。多少次加入! 现在让我们拿一个厕所

In [10]: query2 = Blog.objects.filter(comment__created__gt=from_dt, comment__created__lt=till)
In [11]: print query2.query
SELECT "myapp_blog"."id", "myapp_blog"."name" 
FROM "myapp_blog" 

    INNER JOIN "myapp_comment" 
    ON ("myapp_blog"."id" = "myapp_comment"."blog_id") 

WHERE ("myapp_comment"."created" > 2013-12-15 15:54:50.633000  
AND "myapp_comment"."created" < 2013-12-15
15:54:50.633000 )

请参阅?这是工作的一半。那是因为你在一个关系上过滤,(你可能不会对你要过滤的同一个对象的字段看到这样的影响)所以通过添加过滤器,你需要运行连接两次,仅用于从相关模型中获取数据。

换句话说 - 每次过滤相关模型时,都需要另一个连接,因此使用两个过滤器可以获得两个连接,其中一个只能获得一个连接。如果这是一个ManyToMany关系,那将是 double ,因为你有第三个表。这有助于澄清事情吗?