2012-01-26 12 views
0

例:limit/offset選択でselect_relatedを最適化する方法は?

# 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; 

問題:私は後でそれらにアクセスするとそうでない場合、Djangoは余分なDBプロファイル/アドレス(および他の多くのテーブル)を取得するために呼び出しを行いますので、ここでselect_related使用

は私のクエリをスピードアップループ。しかし、これは反復の開始を加速しますが、OFFSETが大きければ実際には減速します。

1)他に誰かがこの問題を経験していますか? 2)この問題を解決するためのdjangoの回避策はありますか?

これはMySQLクエリエンジンの問題ですが、MySQLのクエリオプティマイザを助けるために私のdjangoコードを構造化できるかどうかを知りたいと思っています。

ありがとうございました

+0

本当にオブジェクトを水和して "q"にする必要がありますか?それとも、本当に特定の価値が必要なのですか?オブジェクトの代わりにvalues_listを返すことによって返されるものと同じです。 – Brandon

答えて

1

「回避方法」はありません。これは予想される動作です。 select_relatedは、それをフィードする外部キーごとにSQL JOINを実行します。これは、データベースが処理する本質的により複雑なクエリです。テーブルの行数が増えるほど時間がかかります。

本当に、このシナリオでできることは、できるだけ多くの最適化をテーブルに適用することです。 profile_idaddress_idの列がまだ索引付けされていない場合は、索引を追加する必要があります(ただし、Djangoは既にこれを行っています)。 .values()または.values_list()を使用して、より限定されたクエリー(処理するために、より少ない正味の仕事を必要とする)。あなたもそこにprofileaddressにフィールドを指定することができます。

しかし、これらのフィールドは、あなたはどちらか、すでにインデックス化、そしてあなたは、すべてのデータを必要としている場合あなたのデータベースにはそれ以上のリソース(RAM、コアなど)を与えてください。負荷が分散しているクラスタを作成してください。

関連する問題