elasticsearch - 结合使用AWS Appsync和DynamoDB,您是否应该通过将相关数据的 “redundant copies”存储在同一张表上(去规范化)来建立关系模型?

标签 elasticsearch nosql amazon-dynamodb aws-appsync non-relational-database

我最近正在阅读this section in the ElasticSearch documentation(或更准确地说是该指南)。它说您应该尝试按预期方式使用非关系数据库,这意味着您应避免在不同表之间进行联接,因为它们并不是为了很好地处理它们而设计的。这也使我想起了DynamoDB文档中的那一部分,该部分指出大多数设计良好的DynamoDB后端仅需要一个表。

让我们以一个食谱数据库为例,其中每个食谱都使用几种成分。每种成分都可以用于许多不同的配方中。

选项1 :对我而言,在AppSync和DynamoDB中进行建模的一种明显方法是,从ingredients表开始,该表的每个成分都有一个项存储所有成分数据,并以ingredient id作为分区键。然后,我有了另一个带有分区键recipesrecipe id表和一个ingredients字段,该字段在数组中存储了所有ingredient id。然后,在AppSync中,我可以通过recipe id进行GetItem请求,然后使用ingredients表上的BatchGetItem解析ingredients字段来查询配方。假设一个食谱平均包含10种成分,那么这意味着将11个GetItem请求发送到DynamoDB表。

选项2:我认为这是一个“类似联接”操作,这显然不是使用非关系数据库的理想方式。因此,或者,我可以执行以下操作:对recipes表上的所有成分数据进行“冗余复制”,不仅将ingredient id保存在那里,还保存ingredients表中的所有其他数据。这可能会大大增加磁盘空间的使用,但是显然磁盘空间很便宜,仅通过执行1个GetItem请求(而不是11个)来提高性能可能是值得的。 As discussed later in the ElasticSearch guide这也将需要一些额外的工作来确保成分数据更新时的并发性。因此,当更新成分时,我可能还必须使用DynamoDB流来更新recipes表中的所有数据。这将需要进行昂贵的扫描以使用更新的成分来查找所有配方,并需要使用BatchWrite来更新所有这些项目。 (尽管成分更新可能很少见,所以增加读取性能可能是值得的。)

我很想听听您对此的看法:

  • 您会选择哪个选项,为什么?
  • 第二种“更非关系的方式”似乎很痛苦,我担心随着更多级别/关系的出现(例如,如果用户可以从配方中创建菜单),当我执行此操作时,最终的复杂性可能会很快失控。必须多次保存相同数据的“冗余副本”。我对关系数据库了解不多,但是当每个数据都有其唯一位置时,这些事情似乎要简单得多(我想这就是“规范化”的意思)。
  • 选项1中的getRecipe是否真的比选项2中的昂贵11倍(性能和成本)?还是我误会了什么?
  • 选项1在关系数据库(例如MySQL)中比在DynamoDB中便宜吗?即使我理解正确,它也是一个联接,它也只是11个(“NoSQL预定方式”)GetItem操作。这还能比1个SQL查询快吗?
  • 如果我有一个非常相关的数据结构,那么像DynamoDB这样的非关系数据库会不是一个不错的选择?还是通过AppSync / GraphQL使其仍然是可行的选择(通过允许确实易于构建的Option 1)?我读到一些意见,即在查询NoSQL数据库时必须不断解决缺少的联接功能,而必须在应用程序端执行此操作是其不合适的主要原因。但是AppSync可能是解决此问题的一种方法。其他意见(包括DynamoDB文档)都提到性能问题是始终只查询一个表的主要原因。
  • 最佳答案

    我知道这已经很晚了,但可能会帮助某个人。
    从实体关系图开始,因为这将有助于确定您的选择。即使在NoSQL中,也存在标准的关系建模方法。
    接下来,定义您的访问模式。遍历所有CRUDL操作,并确保对于每个操作,您都可以访问该操作的特定数据。例如,在选项1中,将配料存储在字段中的阵列中:考虑一种可能需要删除配方中配料的访问模式。为此,您需要知道数组中项目的索引。因此,您必须获取整个数组,找到该项的索引,然后考虑可能的竞争条件,再次发出调用以更新数组。
    在可能的情况下,在您的应用程序中执行此操作效率不高。您也可以在解析器中编写代码,但是尝试使用速度模板语言来编写代码并不值得头疼,请相信我。
    TL; DR将为整个应用程序的实体关系图建模,并仔细考虑所有访问模式。如果关系是一对多的,则可以对数据进行非规范化,使用复合排序键或使用二级索引。如果是多对多,您将开始进入邻接表和其他高级策略。 Alex DeBrie有一些很棒的资源herehere

    关于elasticsearch - 结合使用AWS Appsync和DynamoDB,您是否应该通过将相关数据的 “redundant copies”存储在同一张表上(去规范化)来建立关系模型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52759785/

    相关文章:

    caching - 我们可以使用 Elasticsearch 作为缓存来快速检索数据吗?

    elasticsearch - Elasticsearch: “birthday”异常

    elasticsearch - Elasticsearch 重新索引:WAITING完成

    elasticsearch - 向使用bodybuilder.js生成的DSL查询正文中动态添加过滤器

    python - 使用Python进行全文搜索

    MongoDB - 涉及列表的更新插入

    c++ - 寻找具有某些品质的完全内存数据库

    python - 发电机 : How do I do a putItem but just if key doesn't exists in Python?

    java - UpdateItemRequest - 使用本地二级索引更新多个项目

    python - Boto 3 卡在 Lambda 中