GAE数据存储支持急切的抓取? [英] Does GAE Datastore support eager fetching?

查看:125
本文介绍了GAE数据存储支持急切的抓取?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆