我有一个关于 Google 的数据库 Cloud Datastore 的设计问题。让我用一个例子来解释它:

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

  • 标题
  • 用户 ID
  • ....
  • sumOfScore

  • SumOfScore 应该是所有相关“Score”实体的总和,它们具有
    属性如:
  • 文章编号
  • 用户 ID
  • 得分

  • 在伪 SQL 中:
    sumOfScore = select sum(score) from Score where score.articleId = article.id

    我看到了两种设计方法(使用 Google 的数据存储 API):

    1.) 文章没有属性 sumOfScore;但始终查询:

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

    尽管如此:这将是我使用 Relational-DB 时的首选方式。没有冗余和良好的归一化。
    使用 SQL,您可以只使用一个 join-select 来捕获所有数据。
    但感觉不适合 Cloud Datastore。

    2.) 每当 Score 实体改变时计算 sumOfScore:

    这意味着:每当添加、删除或更改评分实体时,相关文章
    更新 sumOfScore 属性。

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

    缺点:每次更改分数时,都会增加一个查询和一个额外的写入(更新一个 Article 实体)。并且 sumOfScore 可能与实际的 Score 实体不匹配(例如,通过 DB-Console 更改值)

    更有经验的人是怎么想的?这种情况是否有共同的最佳实践?
    引擎盖下的 JPA 或 JDO 实现是什么?

    非常感谢

    莫斯

    最佳答案

    还有第三种不妥协的可能性。
    您将 Score 设为 文章 的子级,并将 sumOfScore 保留在 文章 中。出于排序目的,此字段将派上用场。由于这两个类来自同一个实体组,您可以创建一个 Score 并在一个事务中更新 文章 。您甚至可以通过查询所有 Score 谁的 parent 是给定的 文章 来仔细检查。
    这种方法的问题在于,您每秒只能更新实体 5 次。如果您认为您将有更多的 Activity (请记住,这只是对单个实体的限制,而不是实体表),您应该查看 sharded counter tutorial 或查看 google io's video 对此的解释。
    编辑:
    这是关于同一主题的精彩讨论:How does Google Moderator avoid contention?

    关于java - 数据存储设计 - 如何模拟高效连接,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/7846647/

    10-11 03:35