【问题标题】:Overcoming 30 sub-query limit for google datastore克服谷歌数据存储的 30 个子查询限制
【发布时间】:2016-11-20 15:50:31
【问题描述】:

Google 数据存储区一开始看起来不错,但现在变得如此令人沮丧,但也许只是因为我习惯了关系数据库。总的来说,我对数据存储和 nosql 还很陌生,并且已经进行了大量研究,但似乎找不到解决这个问题的方法。

假设我有一个看起来像这样的 User 类

class User{
  @Id
  Long id;
  String firstName, lastName; 
  List<Key<User>> friends;
}

我有另一个类将模拟用户这样做的事件

class Event{
   Key<User> user;
   Date eventTime;
   List<Key<User>> receivers;
}

现在我要做的是查询我的朋友所做的事件。 以通常的关系方式,我会说:

select * from Event where user in (select friends from User where id = ?)

以此为出发点我尝试做

// Key<User> userKey = ...
User user = ofy.load.type(User.class).key(userKey).first.now;
List<Key<User>> friends = user.getFriends();
ofy.load.type(Event.class).filter("user in", friends).order("-eventTime")list();

但我听说这 30 个子查询的限制使这不可持续,因为我假设最终某人将拥有超过 30 个朋友,更不用说使用“in”子句将保证您无法获得光标来继续加载事件。我做了很多研究并尝试了很多选择,但除了说“为什么是谷歌,为什么”之外,还没有找到解决这个问题的好方法。

我考虑过的事情:

  • 在 event 中添加一个额外的字段,它是用户好友列表的副本,并在 MVP 上使用单个 equals 来查找事件(非常浪费,因为可能有很多很多事件。
  • 一次将事件查询分成 30 个朋友的批次,并以某种方式确定一种方法,以确保从基于时间的合成游标中继续检索,然后将它们合并(问题是边缘情况太多,使读取事件变得非常困难。 )

非常感谢您提供的任何意见,因为我 100% 没有想法

TL;DR ~ GAE 对 in-clause 可以处理和 fml 的项目数量有限制。

【问题讨论】:

  • 我也看到了那个,但与我的情况无关,因为他/她将所有新闻故事加载到内存缓存中,因为新闻对所有登录用户都是全局的。在我的情况下,事件是由用户创建的,但并非所有用户都看到相同的事件,只有他们自己的朋友列表中的人的事件。感谢您的跟进
  • 更不用说我想游标结果,因为可能有很多事件,将所有事件加载到内存缓存中似乎很浪费,这可能随时消失
  • 我提到这主要是为了回答中的建议。
  • 是的,我也在查看,我在问题中提到了我如何考虑将查询分成 30 个批次,如提供的链接中所述。这对新闻来源可能很好,但问题是有太多的边缘情况,无法使其可靠地为我工作。如果前 90 位朋友多年没有活动怎么办?对他们来说,最近发生的事件通常不是最近发生的事件。我想展示最近的 30 个,但最终以很久以前的事件结束。加载很多我不想要的事件是非常棘手的并且非常浪费:(

标签: java google-app-engine google-cloud-datastore objectify nosql


【解决方案1】:

你来自关系数据库背景,所以非规范化的概念可能有点痛苦——我知道它适合我。

现在,您有一个包含所有用户的所有事件的表。这种方法在关系数据库中效果很好,但由于您提到的原因,在数据存储中却是一场噩梦。

因此,要解决这个具体问题,您可以按如下方式重组数据:

  • 所有用户都有两个时间线。一份来自自己的帖子,一份来自朋友的帖子。 (公共内容可能有第三个时间表。)
  • 发布新事件时,会将其写入创建它的用户的时间线以及接收用户的所有时间线。 (您可能希望在用户的时间线中添加第三方时间线的引用,以便在用户决定删除事件时知道要删除的内容)

现在每个用户都可以访问完整的时间线,包括他/她自己的时间线和由第三方事件创建的时间线。这些时间线很容易查询,您根本不需要子选择。

这种方法有缺点:

  1. 写入成本较高。你必须写出比现在更多的时间线。您可能必须将其放入任务队列中,以便有足够的时间写入所有这些时间线。
  2. 您使用了更多的存储空间,但存储空间真的很便宜,我猜从长远来看,存储空间会比运行昂贵的查询便宜。

您得到的回报是通过这种非规范化通过简单查询获得闪电般的快速响应。剩下的就是在 UI 中合并来自不同时间线的响应(您可以在服务器端进行,但我会在 UI 中进行)

【讨论】:

  • 是的,你 100% 正确,非规范化的想法很痛苦,但这种方法在读取/查询方面肯定是最有效的,我想这是 NoSQL 类型数据存储的最大好处,并确保我不要在单独的 MVP 中有一堆重复的数据。非常感谢!
猜你喜欢
  • 2015-09-20
  • 1970-01-01
  • 1970-01-01
  • 2010-11-11
  • 2012-11-20
  • 1970-01-01
  • 2019-12-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多