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



为什么在一个filter子句中应用多个参数不等于为每个参数多次调用filter?

我有博客评论模型。

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

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

虽然这一次的评估时间不到一秒钟:

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

更新我的型号.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。

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

对于这个例子,我使用now = till = from_dt = datetime.now()只是为了举例。此外,从不将from用作变量名。如果你感到惊讶或问为什么,那么停止你正在做的一切,开始学习基本的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关系,那么它将是,因为您将有第三个表。这有助于澄清问题吗?

最新更新