GAE 数据存储是否支持急切获取?
假设我想显示书籍及其作者的列表。在传统的数据库设计中,我会发出一个查询来从 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我认为您隐含地询问 Google App Engine 是否支持 JOIN 以避免 N+1 选择问题。
Google App Engine 不直接支持 JOIN,但允许您使用 ReferenceProperty。
在您的特定场景中,通过两个查询调用,第一个查询调用获取作者:
第二个查询调用查找给定作者的所有书籍:
您可以获得使用 JOIN 的常见 SQL 查询的相同结果。
例如,当我们想要获取 100 本书,每本书都有其作者姓名时,可能会出现 N+1 问题:
在这种情况下,我们需要执行 1+100 个查询,一个用于获取书籍列表,一个用于获取书籍列表。 100 取消引用所有作者对象以获取作者姓名(此步骤在
book.author.name
语句上隐式完成)。解决此问题的一种常见技术是使用
get_value_for_datastore
方法来检索给定书籍的引用作者密钥,而不取消引用它(即数据存储区获取):有一个出色的 您可能想阅读的有关此主题的博客文章。
此方法从
author_key
列表开始,从数据存储中预取作者对象,将每个对象设置为正确的实体书。使用这种方法可以节省大量对数据存储的调用,并且实际上*避免了N+1问题。
* 理论上,在一个书架上有 100 本书,由 100 个不同的作者撰写,我们仍然需要调用数据存储 100+1 次
回答您的问题:
急切获取
有助于避免可怕的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.In you specific scenario, with two query calls, the first one to get the author:
and the second one to find all the books of a given author:
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:
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):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:
eager fetching
helps to avoid the dreaded N+1
problem