GAE 数据存储是否支持急切获取?

发布于 2024-10-01 22:00:38 字数 290 浏览 6 评论 0原文

假设我想显示书籍及其作者的列表。在传统的数据库设计中,我会发出一个查询来从 Book 表以及相关的 Author 表中检索行,这一步骤称为急切获取< /em>.这样做是为了避免可怕的N+1选择问题:如果延迟检索Author记录,我的程序将不得不为每个作者发出单独的查询,可能如下由于列表中有书籍,因此有很多疑问。

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

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

清泪尽 2024-10-08 22:00:38

我认为您隐含地询问 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()
  author= db.ReferenceProperty(Author)

在您的特定场景中,通过两个查询调用,第一个查询调用获取作者:

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

第二个查询调用查找给定作者的所有书籍:

books = Book.all().filter('author=', author).fetch(...)

您可以获得使用 JOIN 的常见 SQL 查询的相同结果。

例如,当我们想要获取 100 本书,每本书都有其作者姓名时,可能会出现 N+1 问题:

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)

有一个出色的 您可能想阅读的有关此主题的博客文章
此方法从 author_key 列表开始,从数据存储中预取作者对象,将每个对象设置为正确的实体书。
使用这种方法可以节省大量对数据存储的调用,并且实际上*避免了N+1问题。

* 理论上,在一个书架上有 100 本书,由 100 个不同的作者撰写,我们仍然需要调用数据存储 100+1 次

回答您的问题:

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

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文