有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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

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

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

  • 头衔
  • 用户ID
  • sumOfScore

SumOfScore应该是所有相关“分数”实体的总和,这些实体具有 属性,如:

  • 文章ID
  • 用户ID
  • 得分

伪SQL中的
sumOfScore=从得分中选择总和(得分)。articleId=物品。身份证

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

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

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

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

2。)每当分数实体发生变化时,计算总和分数:

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

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

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

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

非常感谢

莫斯


共 (2) 个答案

  1. # 1 楼答案

    The first thing I recommend you look into the GAE article about sharding counters

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

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

    See the section here labeled "Transient and frequently updated data"

    最后一种选择;就是使用SQLIts experimental and hot out of the oven (in relation to being used on GAE) but it might be worth looking into.

  2. # 2 楼答案

    还有第三种可能性是不会妥协的

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

    这种方法的问题在于,每秒只能更新实体5次。如果你认为你会有更多的活动(记住,这只是对单个实体的限制,而不是对entier表的限制),你应该查看sharded counter tutorial或查看google io's video解释这一点

    编辑:

    关于这个话题,这里有一个很好的讨论:How does Google Moderator avoid contention?