DynamoDB 吞吐量与搜索时间
DynamoDB Throughput vs Search time
我刚刚发现了我在创建 dynamodb 结构时犯的一个大错误。
我创建了 11 个 table,而其中一个是 table 最常被引用的,其他的是互补的 table。
例如,我有一个 table ,其中我保存名称(连同其他信息)称为 "Names" 和另一个 table 称为 "NamesMappings" 保存所有这些添加到 "Names" table 以便每次用户想要将名称添加到 "Names" table 时,他首先尝试将名称放入 "NamesMappings" 并且仅当它成功时(因此此名称不存在)他可以将该名称添加到 "Names" table 中。如果名称不唯一且不是 "Names" table 中的主键,此过程会有所帮助,并且使用此技术我不必在 "Names" table 中搜索如果该名称存在,但我可以尝试将其添加到 "NamesMappings" table 并且只有在成功时我才知道这是一个唯一的名称。
首先想问一下,这是一种通用的方法还是有更好的方法?
接下来,我发现通过这种设计,我很快达到了 11 tables,每个都有 5 个配置的读写容量,这导致在免费层下总共有 55 个配置的读写容量。然后我明白了为什么我每个月都会收到所有这些付款,因为随着 table 的数量越来越大,我将配置的容量保留为默认值(read/write 容量均为 5),我得到更多并且更多配置容量。
那么,根据这种理解,我应该得出什么结论呢?我是否应该尝试减少 table 的数量,即使在 table 中执行扫描和查询需要更多的努力?或者我应该像我一样拆分 table 但减少这些映射的容量 tables 仅用于指示项目是否存在于另一个 table?
如果我对你的问题的理解正确,你就错过了 NoSQL 数据库的整个概念。
你的 Names
table 应该有一个散列键(类似于主键),它有一个统一生成的标识符(UUID 是一个很好的候选者)。这将自动使此 Table 可通过此唯一标识符进行查询。但是,您说您不知道 ID,而只知道 Name。这使我认为您可以在 Names
table 内的 Name
属性上创建一个 Global Secondary Index (GSI),这样您也可以通过 Name
进行查询。到目前为止,您的 table 结构应该如下所示:
id | name
它们都是可独立查询的,这已经为您提供了很大的灵活性。
现在,假设你想添加 NameMapping
属性(我不知道它是什么样子),你可以简单地在 Names
table 下添加它,摆脱 NamesMappings
table,大大减少您帐户中 WCU 和 RCU 的数量。您的 table 结构现在应该如下所示:
id | name | mappings
假设 mappings
是一个 JSON 对象。
由于您只能查询 DynamoDB 中的顶级属性,您现在可以针对配置了 GSI 的 name
属性执行查询。如果查询returns什么都没有,那么name
就是唯一的。但是假设您仍然需要 mappings
对象中的一些数据,那么您可以通过 name
查询,并且 在您的代码 中,您可以应用 map/filter/reduce 操作 mappings
属性并决定下一步做什么。
请记住,在没有SQL 的世界中,复制是可以的。如果你来自纯粹的 SQL 背景,这可能看起来很可怕,但数据应该以这样一种方式存储在 NoSQL 数据库中,你应该能够一次性获取所有需要的信息,因此避免“joins”(在 NoSQL 数据库中仍然可以进行联接,但是由于实体之间没有牢固的关系,您需要在代码级别手动执行这些联接).为了给您提供一些真实的上下文,假设您有一个 Orders
table,您可以在其中跟踪订购的产品和订单所属的商店:您将同时保存产品和商店对象(而不是他们的 ID,因为它会以 SQL 方式发生)在 Order 对象中,所以如果你想在将来查询给定的 OrderId,你不需要进行额外的调用(又名“加入 ") 到 Product/Store table 以获取信息,因为所有内容都已经存储在 Order 对象中。
我刚刚发现了我在创建 dynamodb 结构时犯的一个大错误。 我创建了 11 个 table,而其中一个是 table 最常被引用的,其他的是互补的 table。 例如,我有一个 table ,其中我保存名称(连同其他信息)称为 "Names" 和另一个 table 称为 "NamesMappings" 保存所有这些添加到 "Names" table 以便每次用户想要将名称添加到 "Names" table 时,他首先尝试将名称放入 "NamesMappings" 并且仅当它成功时(因此此名称不存在)他可以将该名称添加到 "Names" table 中。如果名称不唯一且不是 "Names" table 中的主键,此过程会有所帮助,并且使用此技术我不必在 "Names" table 中搜索如果该名称存在,但我可以尝试将其添加到 "NamesMappings" table 并且只有在成功时我才知道这是一个唯一的名称。
首先想问一下,这是一种通用的方法还是有更好的方法?
接下来,我发现通过这种设计,我很快达到了 11 tables,每个都有 5 个配置的读写容量,这导致在免费层下总共有 55 个配置的读写容量。然后我明白了为什么我每个月都会收到所有这些付款,因为随着 table 的数量越来越大,我将配置的容量保留为默认值(read/write 容量均为 5),我得到更多并且更多配置容量。
那么,根据这种理解,我应该得出什么结论呢?我是否应该尝试减少 table 的数量,即使在 table 中执行扫描和查询需要更多的努力?或者我应该像我一样拆分 table 但减少这些映射的容量 tables 仅用于指示项目是否存在于另一个 table?
如果我对你的问题的理解正确,你就错过了 NoSQL 数据库的整个概念。
你的 Names
table 应该有一个散列键(类似于主键),它有一个统一生成的标识符(UUID 是一个很好的候选者)。这将自动使此 Table 可通过此唯一标识符进行查询。但是,您说您不知道 ID,而只知道 Name。这使我认为您可以在 Names
table 内的 Name
属性上创建一个 Global Secondary Index (GSI),这样您也可以通过 Name
进行查询。到目前为止,您的 table 结构应该如下所示:
id | name
它们都是可独立查询的,这已经为您提供了很大的灵活性。
现在,假设你想添加 NameMapping
属性(我不知道它是什么样子),你可以简单地在 Names
table 下添加它,摆脱 NamesMappings
table,大大减少您帐户中 WCU 和 RCU 的数量。您的 table 结构现在应该如下所示:
id | name | mappings
假设 mappings
是一个 JSON 对象。
由于您只能查询 DynamoDB 中的顶级属性,您现在可以针对配置了 GSI 的 name
属性执行查询。如果查询returns什么都没有,那么name
就是唯一的。但是假设您仍然需要 mappings
对象中的一些数据,那么您可以通过 name
查询,并且 在您的代码 中,您可以应用 map/filter/reduce 操作 mappings
属性并决定下一步做什么。
请记住,在没有SQL 的世界中,复制是可以的。如果你来自纯粹的 SQL 背景,这可能看起来很可怕,但数据应该以这样一种方式存储在 NoSQL 数据库中,你应该能够一次性获取所有需要的信息,因此避免“joins”(在 NoSQL 数据库中仍然可以进行联接,但是由于实体之间没有牢固的关系,您需要在代码级别手动执行这些联接).为了给您提供一些真实的上下文,假设您有一个 Orders
table,您可以在其中跟踪订购的产品和订单所属的商店:您将同时保存产品和商店对象(而不是他们的 ID,因为它会以 SQL 方式发生)在 Order 对象中,所以如果你想在将来查询给定的 OrderId,你不需要进行额外的调用(又名“加入 ") 到 Product/Store table 以获取信息,因为所有内容都已经存储在 Order 对象中。