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 に対してデータベース クエリを取得していることがわかります。メッセージを 1 回だけ照会することに注意してください (予想どおり)。

明らかにこれはかなり遅いので、試してみます:

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...

私は今、各メッセージを個別に、そして各家の外部キーに対してクエリを作成しています - 基本的に呼び出しの数を2倍にしています。

それはうまくいきませんでした。だから今、私は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 '}

...×15...

繰り返しになりますが、恐ろしい家オブジェクトのクエリと、id による完全なメッセージの別のクエリ (defer コマンドなど) を取得しています。

これが ONLY と DEFER の正しい動作かどうかわかりません。FKを評価せずに、情報のみを取得したい(オブジェクトとして、または「値」を使用します-これは機能します)。

編集:

エラーは、return self.house を呼び出したユニコードにありまし

4

1 に答える 1

1

一般的な Django クエリセット、特に何deferをすべきかについていくつかの誤解があるようです。only

defer(fieldname)「今は 'fieldname' を照会しないでください。後で要求するまで待ってください」という意味です。当然、すぐに「house」を要求するため、二重のクエリが返されます。

only(fieldname)名前が示すように、「'fieldname' のみを指定してください」という意味です。したがって、「id」以外のフィールドを参照すると、さらにクエリがトリガーされることに驚かれる理由がわかりません。

ただし、どちらも実際の問題とは何の関係もないことに注意してください。使用する正しいツールは ですselect_related()。これは、ドキュメントで説明されているように、単一のクエリで ForeignKey を追跡するためのものです。

于 2013-03-18T21:19:40.237 に答える