GAE数据存储支持急切的抓取? [英] Does GAE Datastore support eager fetching?
问题描述
Book
表中检索行以及相关的 Author
表,这是一个被称为渴望获取的步骤。这样做是为了避免可怕的 N + 1选择问题:如果Google App Engine数据存储提供了类似的机制,还是N + 1选择问题那么这个平台就不再相关了?
我认为您隐式询问Google App Engine是否支持JOIN以避免 N + 1选择问题。
Google App Engine不直接支持JOIN,而是允许您使用一对多关系
来定义 ReferenceProperty 。
class Author(db.Model):
name = db.StringProperty()
class Book (db.Model):
title = db.StringProperty()
作者= db.ReferenceProperty(作者)
在你的具体情况下,有两个查询调用,作者:
author = Author.all.filter('name =','fooauthor')。get()
和第二个找到给定作者的所有书籍:
books = Book.all()。filter('author =',author).fetch(...)
您可以获得使用JOIN的常见SQL查询的相同结果。
例如,当我们想要获得100本书籍,每本书的作者名称时,就会出现 N + 1 问题:
c $ c> books = Book.all()。fetch(100)for book in book:
print book.author.name
在这种情况下,我们需要执行1 + 100个查询,其中一个用于获取书籍列表,另一个用于取消引用所有作者对象以获取作者姓名(这一步是隐式地在 book.author.n上完成ame
语句)。
解决此问题的一种常见方法是使用 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
问题 em>
- 有些技术(不是开箱即用的):
Let's say I want to display a list of books and their authors. In traditional database design, I would issue a single query to retrieve rows from the Book
table as well as the related Author
table, a step known as eager fetching. This is done to avoid the dreaded N+1 select problem: If the Author
records were retrieved lazily, my program would have to issue a separate query for each author, possibly as many queries as there are books in the list.
Does Google App Engine Datastore provide a similar mechanism, or is the N+1 select problem something that is no longer relevant on this platform?
I think you are implicitly asking if Google App Engine supports JOIN to avoid the N+1 select problem.
Google App Engine does not support JOIN directly but lets you define a one to many relationship
using ReferenceProperty.
class Author(db.Model):
name = db.StringProperty()
class Book(db.Model):
title = db.StringProperty()
author= db.ReferenceProperty(Author)
In you specific scenario, with two query calls, the first one to get the author:
author = Author.all.filter('name =' , 'fooauthor').get()
and the second one to find all the books of a given author:
books = Book.all().filter('author=', author).fetch(...)
you can get the same result of a common SQL Query that uses JOIN.
The N+1 problem could for example appear when we want to get 100 books, each with its author name:
books = Book.all().fetch(100)
for book in books:
print book.author.name
In this case, we need to execute 1+100 queries, one to get the books list and 100 to dereference all the authors objects to get the author's name (this step is implicitly done on book.author.name
statement).
One common technique to workaround this problem is by using get_value_for_datastore
method that retrieves the referenced author's key of a given book without dereferencing it (ie, a datastore fetch):
author_key = Book.author.get_value_for_datastore(book)
There's a brilliant blog post on this topic that you might want to read.
This method, starting from the author_key
list, prefetches the authors objects from datastore setting each one to the proper entity book.
Using this approach saves a lot of calls to datastore and practically * avoids the N+1 problem.
* theoretically, on a bookshelf with 100 books written by 100 different authors, we still have to call the datastore 100+1 times
Answering your question:
- Google App Engine does not support eager fetching
- There are techniques (not out of the box) that helps to avoid the dreaded N+1 problem
这篇关于GAE数据存储支持急切的抓取?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!