Java 数据存储设计-如何模拟高效连接

Java 数据存储设计-如何模拟高效连接,java,google-app-engine,google-cloud-datastore,Java,Google App Engine,Google Cloud Datastore,我有一个关于谷歌数据库云数据存储的设计问题。让我用一个例子来解释: 我得到了具有以下属性的“Article”类型的实体: 头衔 用户ID sumOfScore SumOfScore应该是所有相关“分数”实体的总和,这些实体具有 属性,如: 文章ID 用户ID 得分 在伪SQL中: sumOfScore=从score中选择总和(score),其中score.articleId=article.id 我认为有两种可能性可以设计它(使用谷歌的数据存储API): 1。)物品的核心无属性;但查询

我有一个关于谷歌数据库云数据存储的设计问题。让我用一个例子来解释:

我得到了具有以下属性的“Article”类型的实体:

  • 头衔
  • 用户ID
  • sumOfScore
SumOfScore应该是所有相关“分数”实体的总和,这些实体具有 属性,如:

  • 文章ID
  • 用户ID
  • 得分
在伪SQL中:
sumOfScore=从score中选择总和(score),其中score.articleId=article.id

我认为有两种可能性可以设计它(使用谷歌的数据存储API):

1。)物品的核心无属性;但查询始终为:

这意味着:每次阅读一篇文章时,我都需要对这篇特定的文章进行查询,以计算sumOfScore。 想象一下,向用户显示一个包含100篇文章的列表。这将需要对数据库进行额外的100次查询,以显示每篇文章的分数

尽管如此,在使用关系数据库时,这将是我首选的方法。没有冗余和良好的规范化。 使用SQL,您可以只使用一个连接选择来捕获所有数据。 但对于云数据存储来说,它感觉不太合适

2.)每当更改分数实体时计算核心的SUMMOFSOR:

这意味着:无论何时添加、删除或更改分数实体,相关文章 更新sumOfScore属性

优点:阅读文章时不需要额外的查询。sumOfScore在实体本身上是冗余的

缺点:每次更改分数时,都会有一个额外的查询和一个额外的写入(更新文章实体)。sumOfScore可能与实际得分实体不匹配(例如,通过DB控制台更改值)

更有经验的人会怎么想?对于这种情况是否有共同的最佳实践? JPA或JDO的实现到底在做什么

非常感谢


Mos

第三种可能性不会妥协

您为文章的子项打分,并将汇总表保存在文章中。出于排序目的,此字段将派上用场。由于这两个类来自同一实体组,因此您可以在事务中创建分数,并更新文章。您甚至可以通过查询所有分数来进行双重检查谁的父母是给定的文章

这种方法的问题在于,每秒只能更新实体5次。如果您认为您将有更多的活动(请记住,这只是对单个实体的限制,而不是对entier表的限制),那么您应该查看或查看说明

编辑: 关于这个话题,这里有一个很好的讨论:

这是GAE最佳实践中的一篇文章,涉及如何处理计数器/金额。这可能有点棘手,因为每次更新一个元素时,都必须使用逻辑随机选取一个碎片计数器;当你检索你的计数时,你实际上是在获取一组实体并对它们求和。我已经走了这条路,但不会在这里提供关于我是如何做到这一点的代码,因为我还没有对它进行战斗测试。但是,如果您只是到处复制/粘贴示例分片代码,那么您的代码可能会很快变得草率,因此,如果您决定这样做,请创建一个抽象的或类型化的计数器类来重用您的分片逻辑

另一种选择是使用模糊计数。此方法使用memcache,以牺牲准确性为代价提供更好的性能


最后一种选择;就是使用SQL

实际上,您并没有使用Bigtable—您使用的是AppEngine数据存储,它恰好构建在Bigtable的基础上,但提供了更多的功能。