Django 使用 Q 对象优化查询集
Django Optimisation of a queryset with Q objects
我正在使用 Django 1.8。
我有一个查询集需要一个逻辑 "or" 和一个 "and"。
它给出:
MyModel.objects.filter(
Q(start__gt=today) | Q(end__lte=today),
active=True).update(active=False)
正如您可能理解的那样,它应该获取每个不应该启动的活动 MyModel 实例,以及已经完成的实例,然后停用它们。
"start" 和 "end" 是日期字段,"active" 是布尔值。
它有效,但它生成的查询远未得到优化。我希望能够通过过滤 "active" 状态来开始查询,然后检查其他两个字段,因为在我的数据库中,我有数千个条目,但只有少数条目具有 active=True。我会说这个布尔测试比比较更快。
我无法对参数重新排序,因为前者带有两个 Q() 是一个定位参数,而后者是一个名称参数,我无法链接多个 filter() 因为它会生成一个 "or",而不是 "and".
有办法吗?
您可以通过 chaining filters
MyModel.objects.filter(
active=True
).filter(
Q(start__gt=today) | Q(end__lte=today)
).update(active=False)
补充说明
我认为您不会通过先过滤 active
然后过滤 start
和 end
来获得任何性能提升。因为 chaning 或 not-chaining 将执行相同的查询。这是来自 Django docs 的示例:
Entry.objects.exclude(pub_date__gt=datetime.date(2005, 1, 3), headline='Hello')
In SQL terms, that evaluates to:
SELECT ...
WHERE NOT (pub_date > '2005-1-3' AND headline = 'Hello')
请注意,过滤器已在上面的示例中链接在一起,但在 SQL 查询中,两个过滤器被放在一起。
提升数据库性能
查找数据库索引(如评论中所指出)。
考虑在内存中缓存数据库(例如,参见 Memcached)。
首先,Django ORM 生成的 SQL 命令可能不会具有与您的 .filter
方法相同顺序的条件子句。所以不用担心 "optimal" 顺序。
其次,无论子句以何种顺序出现在SQL命令中,数据库引擎都会优化请求并生成适合您的数据分布的执行计划。任何值得考虑的数据库引擎都会保留一些数据分布统计信息。如果active
条记录的比例实际上是本次查询中的最佳判别式,则优先过滤
我正在使用 Django 1.8。
我有一个查询集需要一个逻辑 "or" 和一个 "and"。 它给出:
MyModel.objects.filter(
Q(start__gt=today) | Q(end__lte=today),
active=True).update(active=False)
正如您可能理解的那样,它应该获取每个不应该启动的活动 MyModel 实例,以及已经完成的实例,然后停用它们。
"start" 和 "end" 是日期字段,"active" 是布尔值。
它有效,但它生成的查询远未得到优化。我希望能够通过过滤 "active" 状态来开始查询,然后检查其他两个字段,因为在我的数据库中,我有数千个条目,但只有少数条目具有 active=True。我会说这个布尔测试比比较更快。
我无法对参数重新排序,因为前者带有两个 Q() 是一个定位参数,而后者是一个名称参数,我无法链接多个 filter() 因为它会生成一个 "or",而不是 "and".
有办法吗?
您可以通过 chaining filters
MyModel.objects.filter(
active=True
).filter(
Q(start__gt=today) | Q(end__lte=today)
).update(active=False)
补充说明
我认为您不会通过先过滤 active
然后过滤 start
和 end
来获得任何性能提升。因为 chaning 或 not-chaining 将执行相同的查询。这是来自 Django docs 的示例:
Entry.objects.exclude(pub_date__gt=datetime.date(2005, 1, 3), headline='Hello')
In SQL terms, that evaluates to:
SELECT ... WHERE NOT (pub_date > '2005-1-3' AND headline = 'Hello')
请注意,过滤器已在上面的示例中链接在一起,但在 SQL 查询中,两个过滤器被放在一起。
提升数据库性能
查找数据库索引(如评论中所指出)。
考虑在内存中缓存数据库(例如,参见 Memcached)。
首先,Django ORM 生成的 SQL 命令可能不会具有与您的 .filter
方法相同顺序的条件子句。所以不用担心 "optimal" 顺序。
其次,无论子句以何种顺序出现在SQL命令中,数据库引擎都会优化请求并生成适合您的数据分布的执行计划。任何值得考虑的数据库引擎都会保留一些数据分布统计信息。如果active
条记录的比例实际上是本次查询中的最佳判别式,则优先过滤