假设我想显示书籍及其作者列表。在传统的数据库设计中,我会发出一个查询来从Book
表中检索行以及相关的Author
表,这一步被称为,渴望提取。这是为了避免可怕的N + 1选择问题:如果Author
记录被懒惰地检索到,我的程序将不得不为每个作者发出一个单独的查询,可能与列表中的书籍一样多。GAE数据存储支持渴望提取吗?
Google App Engine Datastore是否提供了类似的机制,或者是N + 1选择问题,在此平台上不再相关?
假设我想显示书籍及其作者列表。在传统的数据库设计中,我会发出一个查询来从Book
表中检索行以及相关的Author
表,这一步被称为,渴望提取。这是为了避免可怕的N + 1选择问题:如果Author
记录被懒惰地检索到,我的程序将不得不为每个作者发出一个单独的查询,可能与列表中的书籍一样多。GAE数据存储支持渴望提取吗?
Google App Engine Datastore是否提供了类似的机制,或者是N + 1选择问题,在此平台上不再相关?
我认为你隐含地询问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次
回答你的问题:
非常感谢!是否有Java的'ReferenceProperty'? – 2010-11-11 11:32:50
@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