2009-04-13 15 views
6

ジャンゴとクエリ効率のネストされたコレクションについて質問:私はこの1つのように答えの多くを見る

Printing a list of persons with more than one home each home with more than one

私は同様のモデルでその答えを試してみましたが、それはやってひどく非効率的な方法のように思えますこの。それぞれの反復は別々のクエリを作成し、データベースに何千ものクエリをもたらすことがあります。私はあなたがクエリセットをキャッシュすることができますが、それはまだ非常に間違っているように思う。だから質問は、あなたはその方法を使用していますか?そうでない場合、どうやってそれをしますか?

答えて

6

これは非常に良い質問であり、DjangoのORMフレームワークに限定されるものではありません。

私はいつもそれがオブジェクト・リレーショナル・マッピング(ORM)フレームワークが解決する問題のいくつかを覚えておくことが重要だと感じ:

  • オブジェクト指向CRUDを:アプリケーションの残りの部分はに基づいている場合オブジェクト指向の強力なオブジェクト指向の原則は、オブジェクトを使用してデータの永続性にアクセスすることで、コードをより一貫して、内部的に一貫して、時にはより短くすることができます。

  • パーシスタンスレイヤカプセル化:ORMは、アプリケーションにDBアクセス用のクリアレイヤーを提供します。それは、いわゆるDRY(自分自身を繰り返さない)原則の典型である、1つのスポットでデータを読み書きするために必要なすべての機能をカプセル化します。すべてのDBアクセスが1つの場所を通過するため、モデルの変更、すべてのDB対面選択と挿入/更新コードがアプリ全体ではなく1つの場所にあるため、セキュリティです。テストは、データモデルを模倣し、明確に記述されていればアクセスするのが簡単だからです。

  • SQLセキュリティ:それはインジェクション攻撃などに対する生のSQLの使用を確保するのは簡単ですが、あなたが持っていることはありませんので、あなたはあなたのためにそれを行うDB-接触のシングルポイントとして、ORMフレームワークを持っている場合、それはさらに簡単ですそれについて考える。

速度がリストにないことに注意してください。 ORMは、コードとデータベース間の間接的なレベルです。確かにORMデザイナーは優れたSQL文を生成するフレームワークを作成する責任がありますが、ORMは実行効率ではなくコードおよびアーキテクチャレベルの効率を提供することを意図しています。 SQLに関する基本的な本を読んだ開発者は、常により良いパフォーマンスをDBに直接話すことができます。

これに対抗する戦略は確かにあります.Djangoでは、ozanが言及したようにselect_related()、サイト/ビュー/その他のキャッシュがありますが、直接SQL文と同じパフォーマンスは得られません。このため、私はスピードが必要な時に生のSQL文を発行するためのメカニズムを提供していないORMフレームワークを決して使用しません。たとえば、多くのテーブルを結合するデータベースから大規模なレポートを生成する際に、生のSQLを使用することがよくあります。 ORM方法は分を取ることができる、SQLの方法は秒かかることができます。

私は個々のクエリについて心配することはまずありません。 ORM層に来る人のための私のアドバイスは、ORMのデータベースアクセスをnannyしないことです。アプリケーションやモジュールを記述し、それをプロファイリングして、パフォーマンスの向上が本当に必要な領域を調整するか、またはcaching/select_relatedを使用してアプリケーションのDB-chattiness全体を減らします。

+0

+1正解。 :) –

+0

すばらしい答え! select_relatedで遊んだ後、私はそれを直接SQLに対してベンチマークすることに決めました。 1,000,000件を超えるリクエストがあると聞いても驚かないでしょう。直接SQLは15倍高速です。 selectと関連していても、djangoはまだデータベースとたくさん話したいと思っています。 – Matt

+0

Hmmm ...面白い!ブログはありますか?あなたは燃え尽きることを避けるために慎重にフレーズをすべて練習する必要がありますが、ベンチマークの手順と結果はコミュニティにとって非常に興味深いものになります。 –

4

select_related() queryset methodを使用すると、データベースクエリの数を減らすことができます。深さを指定することもできます。したがって、電話番号モデルに追加の外部関係がある場合は、select_related(depth = 2)を使用して、関連するエンティティの「レベル」を選択しないようにします。

+0

ええと、私が読んだ本では、特定の関連モデルを選択できるとは言いませんでした。私はselect_related()を使うことで、私が必要としなかった他の4つか5つのmanytomany関係を引き上げるという問題に遭遇していました。質問をする前にdjangoproject.comを読む時間!ありがとうございました。 – Matt

関連する問題