1

我有 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").  # only get 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...

所以再一次,我得到了可怕的房子对象查询和另一个按 id 查询完整消息的查询(如 defer 命令)。

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

编辑:

错误出现在我调用 return self.house的unicode中

4

1 回答 1

1

You seem to have a few misunderstandings about Django querysets in general, and what defer and only are supposed to do in particular.

defer(fieldname) means "Don't query for 'fieldname' now, wait until I ask for it later". So naturally, since you then proceed to ask for 'house' immediately, you will get double queries.

only(fieldname) means - as the name implies - "only give me 'fieldname'". So I don't know why you would be surprised that then referring to other fields than 'id' would trigger a further query.

However, you should note that neither of those has anything to do with your actual problem: the correct tool to use there is select_related(), which as the documentation explains is for following the ForeignKey in a single query.

于 2013-03-18T21:19:40.237 回答