【问题标题】:Does GAE Datastore support eager fetching?GAE Datastore 是否支持 Eager fetching?
【发布时间】:2010-11-11 07:15:34
【问题描述】:

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

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

【问题讨论】:

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


    【解决方案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 次查询,1 次获取书籍列表,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 问题

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-01-23
    • 1970-01-01
    • 1970-01-01
    • 2014-08-21
    • 1970-01-01
    • 2016-08-22
    • 1970-01-01
    相关资源
    最近更新 更多