Django:推迟并且只是不工作

时间:2013-03-18 21:06:48

标签: django query-optimization

我有2个模特,一个房子和一条消息。一条消息有FK到房子:

model House:
   attribute1 = models.CharField("")
   ...more stuff...

model Message:
   house = models.ForeignKey(House)
   ...more stuff...

我用house_id = 3创建了15条消息:Message(house_id = 3).save()

我的问题是查询的速度有多慢。当我这样做时:

Message.objects.filter(house_id = 3)

我收到以下问题:

{u'time': u'0.030', u'sql': u'SELECT `home_message`.`id`, `home_message`.`house_id`,       FROM `home_message` WHERE `home_message`.`house_id` = 3 '}
{u'time': u'0.027', u'sql': u'SELECT `home_house`.`id`, `home_house`.`is_active`,  FROM `home_house` WHERE `home_house`.`id` = 3 '}
{u'time': u'0.027', u'sql': u'SELECT `home_house`.`id`, `home_house`.`is_active`,  FROM `home_house` WHERE `home_house`.`id` = 3 '}
{u'time': u'0.027', u'sql': u'SELECT `home_house`.`id`, `home_house`.`is_active`,  FROM `home_house` WHERE `home_house`.`id` = 3 '}

...(15次,每封邮件一次)

所以我看到我的消息中的每个house_id都有一个数据库查询。请注意,我只查询Messages ONCE(如预期的那样)。

显然这很慢,所以我试试:

Message.objects.filter(house_id = 3).defer('house')

令人惊讶的是,这使情况更糟。查询现在是:

{u'time': u'0.028', u'sql': u'SELECT `home_message`.`id` FROM `home_message` WHERE `home_message`.`house_id` = 3 '}
{u'time': u'0.024', u'sql': u'SELECT `home_message`.`id`, `home_message`.`house_id` FROM `home_message` WHERE `home_message`.`id` = 1 '}
{u'time': u'0.027', u'sql': u'SELECT `home_house`.`id`, `home_house`.`is_active`, ` FROM `home_house` WHERE `home_house`.`id` = 3 '}
{u'time': u'0.024', u'sql': u'SELECT `home_message`.`id`, `home_message`.`house_id` FROM `home_message` WHERE `home_message`.`id` = 2 '}
{u'time': u'0.027', u'sql': u'SELECT `home_house`.`id`, `home_house`.`is_active`, ` FROM `home_house` WHERE `home_house`.`id` = 3 '}
...x15...

我现在正在为每个房屋外键单独查询每条消息 - 基本上是调用次数加倍。

那不起作用。所以现在我尝试“只有”django    Message.objects.filter(house_id = house_id).only(“id”)。 #只获取ID!

我现在发送的查询:

{u'time': u'0.025', u'sql': u'SELECT `home_message`.`id` FROM `home_message` WHERE `home_message`.`house_id` = 3 '}
{u'time': u'0.024', u'sql': u'SELECT `home_message`.`id`, `home_message`.`house_id` FROM `home_message` WHERE `home_message`.`id` = 1 '}
{u'time': u'0.026', u'sql': u'SELECT `home_house`.`id`, `home_house`.`is_active`,  WHERE `home_house`.`id` = 3 '}
{u'time': u'0.024', u'sql': u'SELECT `home_message`.`id`, `home_message`.`house_id` FROM `home_message` WHERE `home_message`.`id` = 2 '}
{u'time': u'0.026', u'sql': u'SELECT `home_house`.`id`, `home_house`.`is_active`,  WHERE `home_house`.`id` = 3 '}

... X15 ...

所以再一次,我得到了可怕的house对象查询和另一个id的完整Message的查询(比如defer命令)。

我不明白这是否是ONLY和DEFER的正确行为。我希望只获得信息(作为一个对象,或者我会使用“值” - 这确实有效。)而不评估FK。

编辑:

错误发生在我打过的 unicode 中     返回self.house

1 个答案:

答案 0 :(得分:1)

您似乎对Django查询集有一些误解,特别是deferonly应该做什么。

defer(fieldname)表示“现在不要查询'fieldname',等到我以后要求它”。很自然地,既然你立即开始询问“房子”,你就会得到双重查询。

only(fieldname)意思是 - 顾名思义 - “只给我''fieldname'”。所以我不知道你为什么会因为引用其他字段而不是“id”会引发进一步的查询而感到惊讶。

但是,您应该注意,这些都与您的实际问题无关:正确使用的工具是select_related(),正如文档所解释的那样,是在单个查询中跟踪ForeignKey。 / p>