GAE数据存储是否支持渴望获取?

时间:2010-11-11 07:15:35

标签: google-app-engine google-cloud-datastore eager-loading database-optimization

假设我要显示一系列书籍及其作者。在传统的数据库设计中,我会发出一个查询来检索Book表中的行以及相关的Author表,这一步称为 eager fetching 。这样做是为了避免可怕的 N + 1选择问题:如果懒惰地检索Author记录,我的程序将不得不为每个作者发出一个单独的查询,可能与列表中有书籍。

Google App Engine数据存储区是否提供了类似的机制,或N + 1选择问题是否与此平台不再相关?

1 个答案:

答案 0 :(得分: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 此方法从author_key列表开始,从数据存储区中将作者对象预设为每个正确的实体书。
使用这种方法可以节省大量数据存储区调用,实际上 * 可以避免 N + 1 问题。

*理论上,在100个不同作者编写的100本书的书架上,我们仍然需要将数据库调用100 + 1次

回答你的问题:

  • Google App Engine不支持 渴望获取
  • 有技术(不是开箱即用) 有助于避免可怕的 N + 1 问题