django查询中or-ing Q对象的性能影响

Posted

技术标签:

【中文标题】django查询中or-ing Q对象的性能影响【英文标题】:Performance impact of or-ing Q objects in django query 【发布时间】:2015-03-03 13:33:08 【问题描述】:

我正在执行一个将一堆 Q 组合在一起的查询,这似乎需要很多时间。这是一些伪代码

query_params = []
for i in range(80): #there are about 80ish Q objects being created
    query_params.append(Q(filter_stuff))

那我还是他们一起

query_params = reduce(or_, query_params)

当我执行查询时

query = list(MyModel.objects.filter(query_params))

它挂了很长时间。我知道这是一个非常笼统的问题,如果不深入了解数据结构(在这里很难给出),就很难给出诊断。但我只是好奇在 django 查询中 or-ing Q 对象是否存在固有的性能影响

【问题讨论】:

你在谈论将 80 个条件组合在一起,无论如何这都会很慢......我建议找出一种更好的方法来查询你想要的记录 @doniyor 不,模型的字段很少,但我试图找到它们的特定对(即 q1 = Q(field1=val1, field2=val2), q2 = Q(field1=val3, field2=val4) 等...) 我建议创建配对索引。 调用 Django shell 并试用您的代码。我的猜测是对数据库的实际调用真的很慢,其余的代码并没有那么多。无论如何,如果您遇到性能问题:分析您的代码,看看哪一行很慢。 Warath-coder 对索引的看法可能是正确的,但请确保在整个代码中保持相同的顺序:如果您在 (field1, field2) 上创建索引,则应该在 Q(field1=..., field2=...) 上查询,而不是在 Q(field2=..., field1=...) 上查询,否则复合索引获胜不行。 您是否尝试过调试工具栏来查看您正在生成的 SQL 以及实际需要多长时间?现在 80 个条件太疯狂了^^,你能告诉我们(没有代码)你想要实现什么。一定有更好/更简单的方法。 【参考方案1】:

能够通过减少Qobjects 的数量来显着缩短查询的长度。它们都是这样的格式:

q1 = Q(field1=field1_val1, field2=field2_val1)
q2 = Q(field1=field1_val2, field2=field2_val2)
#...etc

我最终将它们按 field1 值分组:

q_dict = field1_val1: [all field_2 values paired with field1_val1], ...

然后我的 q 个对象看起来像这样:

for field1_val, field2_vals = q_dict.items():
    query_params.append(Q(field1=field1_val, field2__in=field2_vals))

这最终显着减少了我的 Q 对象数量,并且查询运行得更快

【讨论】:

以上是关于django查询中or-ing Q对象的性能影响的主要内容,如果未能解决你的问题,请参考以下文章

Django-orm:单表查询基于对象和双下划线的多表操作集合查询分组查询F查询和Q查询

Django中Q查询及Q()对象

Django 过滤器 OR - q 对象性能与 I 性能

Django QuerySet 与原始查询性能

Django篇之F,Q

Django Q 对象(复杂查询)是不是安全?