Django使用Q对象优化查询集

时间:2015-06-04 16:31:41

标签: sql django django-queryset django-q

我正在使用Django 1.8。

我有一个需要逻辑"或"的查询集。和"和"。 它给出了:

MyModel.objects.filter(
    Q(start__gt=today) | Q(end__lte=today),
    active=True).update(active=False)

正如您可能了解的那样,它应该采取每个尚未启动的活动MyModel实例,以及已完成的实例,并停用它们。

"开始"和"结束"是DateFields,"活跃"是一个布尔值。

它可以工作,但它生成的查询远未被优化。我希望能够通过过滤" active"来启动查询。状态,然后检查其他两个字段,因为在我的数据库中,我有数千个条目,但只有少数有active = True。我会说这个布尔测试比比较更快。

我无法重新排序参数,因为前者带有两个Q()是一个定位参数而后者是一个名称参数,我不能链接多个filter()因为它生成一个"或",而不是"和"。

有办法做到这一点吗?

2 个答案:

答案 0 :(得分:1)

首先,Django ORM生成的SQL命令可能没有条件子句与JSON.stringify()方法的顺序相同。所以不要担心“最佳”订单。

其次,无论子句以何种顺序出现在SQL命令中,数据库引擎都会优化请求并生成适合您的数据分发的执行计划。任何值得考虑的数据库引擎都会保留一些数据分布如果.filter记录的比例实际上是此查询中的最佳判别式,那么它将首先被过滤。

答案 1 :(得分:0)

您可以chaining filters

执行此操作
active

附加说明

首先过滤start然后过滤endEntry.objects.exclude(pub_date__gt=datetime.date(2005, 1, 3), headline='Hello') ,我认为您不会获得任何性能提升。因为chaning或 not -chaining将执行相同的查询。以下是Django docs的一个例子:

SELECT ...
WHERE NOT (pub_date > '2005-1-3' AND headline = 'Hello')
     

在SQL术语中,评估为:

if (Date.parse(currentDate) >= Date.parse(maxDate)) {
  alert('error');
}

请注意,过滤器已在上面的示例中链接,但在SQL查询中,两个过滤器都是一起使用的。

提升数据库性能

  1. 查找数据库索引(如注释中所示)。

  2. 考虑在内存中缓存数据库(例如,请参阅Memcached)。