2

本とその著者のリストを表示したいとしましょう。従来のデータベース設計では、1 つのクエリを発行しBookて、関連するAuthorテーブルだけでなくテーブルからも行を取得していました。これは、恐ろしいN+1 選択の問題を回避するために行われます。レコードが遅延して取得された場合Author、私のプログラムは著者ごとに個別のクエリを発行する必要があります。おそらくリストにある本の数と同じ数のクエリです。

Google App Engine Datastore は同様のメカニズムを提供していますか、それとも N+1 選択の問題はこのプラットフォームではもはや関係ないものですか?

4

1 に答える 1

3

N+1 選択の問題を回避するために、Google App Engine が JOIN をサポートしているかどうかを暗黙のうちに尋ねていると思います。
Google App Engine は JOIN を直接サポートしていませんが、ReferencePropertyone to many relationshipを使用して定義できます。

class Author(db.Model):
  name = db.StringProperty()

class Book(db.Model):
  title = db.StringProperty()
  author= db.ReferenceProperty(Author)

特定のシナリオでは、2 つのクエリ呼び出しで、最初の呼び出しで作成者を取得します。

author = Author.all.filter('name =' , 'fooauthor').get()

2 つ目は、特定の著者のすべての本を検索します。

books = Book.all().filter('author=', author).fetch(...)

JOIN を使用する一般的な SQL クエリと同じ結果を得ることができます。

N+1問題は、たとえば、100 冊の本をそれぞれの著者名とともに取得する場合に発生する可能性があります。

books = Book.all().fetch(100)
for book in books:
    print book.author.name

この場合、1 + 100 のクエリを実行する必要があります。1 つは本のリストを取得するため、100 は著者の名前を取得するためにすべての著者オブジェクトを逆参照するためです (このステップはbook.author.nameステートメントで暗黙的に実行されます)。

この問題を回避するための一般的な手法の 1 つget_value_for_datastoreは、特定の本の参照先の著者のキーを逆参照せずに取得する方法 (つまり、データストア フェッチ) を使用することです。

author_key = Book.author.get_value_for_datastore(book)

このトピックに関する素晴らしいブログ投稿がありますので、ぜひお読みください。
このメソッドは、author_keyリストから始めて、データストアから著者オブジェクトをプリフェッチし、それぞれを適切なエンティティ ブックに設定します。
このアプローチを使用すると、データストアへの多くの呼び出しが節約され、実質的に* N+1問題が回避されます。

* 理論的には、100 人の異なる著者によって書かれた 100 冊の本がある本棚では、データストアを 100+1 回呼び出す必要があります

あなたの質問に答える:

  • Google App Engine は熱心なフェッチをサポートしていません
  • 恐ろしいN + 1問題を回避するのに役立つ手法(すぐに使用できるものではありません)があります
于 2010-11-11T10:36:49.970 に答える