如何使用限制/偏移选择优化select_related?

时间:2012-01-26 18:03:10

标签: mysql django

示例:

# consider the following query run in a loop
q = Users.objects.all().select_related('profile', 'address')[start:start+batchsize]

# assume start == 1,000,000 and batchsize == 1000
print q.query

SELECT ... LEFT OUTER JOIN profile ... LIMIT 1000 OFFSET 1000000;

问题:

在这里使用select_related会加快我的查询速度,否则,当我稍后在循环中访问它们时,django将进行额外的数据库调用以获取配置文件/地址(以及许多其他表)。然而,虽然这会加速迭代的开始,但是当OFFSET很大时,它实际上会变慢。

1)还有其他人遇到过这个问题吗? 2)django有没有解决这个问题的方法?

我有点怀疑这是MySQL查询引擎的一个问题,但只是想知道我是否可以构造我的django代码来帮助MySQL中的查询优化器。

由于

1 个答案:

答案 0 :(得分:1)

这里没有真正的“解决方法”。这是预期的行为。 select_related为您提供的每个外键执行SQL JOIN。对于要处理的数据库而言,这是一个固有的更复杂的查询。表中的行越多,所需的时间就越长。

实际上,在这种情况下你所能做的就是尽可能多地对你的表进行优化。如果profile_idaddress_id列尚未编入索引,则应为其添加索引(但我怀疑Django已经为您完成了这些操作。

如果您不需要所有字段,则可以尝试使用.values().values_list()发送更有限的查询(需要更少的网络工作)。您甚至可以在那里的profileaddress指定字段。

但是,如果这些字段已经编入索引,并且您需要所有数据,则您必须处理缓慢或对数据库采取更严厉的措施。您可以将它隐藏到自己的服务器(如果它还没有),如果服务器功能不足,则为服务器提供更多资源(RAM,核心等),创建一个集群来分配负载等等。