2

假设我想显示书籍及其作者列表。在传统的数据库设计中,我会发出一个查询来从Book表中检索行以及相关的Author表,这一步被称为,渴望提取。这是为了避免可怕的N + 1选择问题:如果Author记录被懒惰地检索到,我的程序将不得不为每个作者发出一个单独的查询,可能与列表中的书籍一样多。GAE数据存储支持渴望提取吗?

Google App Engine Datastore是否提供了类似的机制,或者是N + 1选择问题,在此平台上不再相关?

回答

3

我认为你隐含地询问Google App Engine是否支持JOIN,以避免N + 1选择问题
Google App Engine不直接支持JOIN,但可以使用ReferenceProperty定义one to many relationship

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

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

在你的具体情况,有两个查询电话,第一个拿到作者:

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

,第二个找到一个给定作者的所有书籍:

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个查询,一个获取书籍列表和100,取消引用所有作者对象以获取作者姓名(这一步隐含在book.author.name声明中完成)。

的常用技术来解决此问题是使用get_value_for_datastore方法检索引用作者的特定书的关键不取消引用它(即,数据存储,提取):

author_key = Book.author.get_value_for_datastore(book) 

有这个辉煌的blog post您可能想要阅读的主题。
该方法从​​列表开始,将作者对象从数据存储中预取,将每个对象设置为适当的实体书籍。
使用这种方法可以节省大量的数据存储调用,并且几乎可以避免N + 1问题。

*理论上,与100本书由100名不同的作者写了一个书架,我们还是要调用数据存储100 + 1次

回答你的问题:

  • 谷歌应用程序引擎不不支持 渴望获取
  • 有技术(不开箱),其 有助于避免可怕的N + 1 问题
+0

非常感谢!是否有Java的'ReferenceProperty'? – 2010-11-11 11:32:50

+0

@Jen看看[这里](http://code.google.com/intl/it-IT/appengine/docs/java/datastore/relationships.html#Owned_One_to_Many_Relationships) – systempuntoout 2010-11-11 11:38:12