我有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
答案 0 :(得分:1)
您似乎对Django查询集有一些误解,特别是defer
和only
应该做什么。
defer(fieldname)
表示“现在不要查询'fieldname',等到我以后要求它”。很自然地,既然你立即开始询问“房子”,你就会得到双重查询。
only(fieldname)
意思是 - 顾名思义 - “只给我''fieldname'”。所以我不知道你为什么会因为引用其他字段而不是“id”会引发进一步的查询而感到惊讶。
但是,您应该注意,这些都与您的实际问题无关:正确使用的工具是select_related()
,正如文档所解释的那样,是在单个查询中跟踪ForeignKey。 / p>