DynamoDB中本地和全局索引之间的区别

我很好奇这两个二级指标和它们之间的差异。 很难想象这是怎么回事。 而且我认为,这将帮助更多的人,而不仅仅是我。

本地二级索引仍然依赖于原始的哈希键。 当你提供一个带有散列+范围的表时,把LSI看作散列+范围1,散列+范围2,散列+范围6。 你可以得到5个更多的范围属性来查询。 另外,只有一个预置吞吐量。

全局二级索引定义了一个新的范例 – 每个索引不同的散列/范围键。
这打破了每个表的一个散列键的原始用法。 这也是为什么在定义GSI时,您需要为每个索引添加预置吞吐量并为其付费。

有关这些差异的更多详细信息可以在GSI公告中find

以下是文档中的正式定义:

全局二级索引 – 具有散列和范围键的索引,可以与表上的索引不同。 全局二级索引被视为“全局”,因为索引上的查询可跨越所有分区中的表中的所有数据。

本地二级索引 – 与表具有相同散列键但具有不同范围键的索引。 本地二级索引是“本地”的,因为本地二级索引的每个分区都被限定为具有相同散列键的表分区。

然而,在关键定义方面,差异超出了可能性。 以下找出将直接影响维护指标的成本和努力的一些重要因素:

  • 吞吐量:

本地二级索引消耗表中的吞吐量。 当您通过本地索引查询logging时,操作会消耗表中的读取容量单位。 在具有本地索引的表中执行写入操作(创build,更新,删除)时,会有两个写入操作,一个用于索引的另一个表。 两个操作都将消耗表中的写入容量单位。

全局二级索引具有自己的configuration吞吐量,当您查询索引时,操作将消耗索引的读取容量,当您在具有全局索引的表中执行写入操作(创build,更新,删除)时,会有两个写操作,另一个为表索引*。

*在为全球二级指数定义供应吞吐量时,请确保您特别注意以下要求:

为了使表写入成功,为表和其所有全局二级索引设置的吞吐量设置必须具有足够的写入容量以适应写入; 否则,对表的写入将受到限制。

  • pipe理:

本地二级索引只能在创build表时创build,没有办法将本地二级索引添加到现有表中,同样,一旦创build了索引,也不能将其删除。

全局二级索引可以在创build表并添加到现有表时创build,也可以删除现有的全局二级索引。

  • 读一致性:

本地二级索引支持最终一致性或强一致性,而全球二级索引仅支持最终一致性。

  • 投影:

本地二级索引允许检索未投影到索引的属性(尽pipe额外的成本是:性能和消耗的容量单位)。 使用全局二级索引,只能检索投影到索引的属性。

关于定义为二级索引的键的唯一性的特殊考虑:

在本地二级索引中,范围键值不需要对于给定的哈希键值是唯一的,同样的情况适用于全局二级索引,键值(哈希和范围)不需要是唯一的。

资料来源: http : //docs.aws.amazon.com/amazondynamodb/latest/developerguide/SecondaryIndexes.html

这些是索引可能的search:

  • 哈希
  • 通过哈希+范围
  • 通过哈希+本地索引
  • 按全球指数
  • 按全球指数+范围指数

表的哈希和范围索引:这些是以前版本的Amazon AWS SDK的常用索引。

全局和本地索引:除了表的现有哈希和范围索引外,这些是在表上创build的“附加”索引。 全局索引与散列相似。 范围索引的行为与用于表的散列的范围索引类似。 在你的代码中的实体模型中,getter必须以这种方式注释:

  • 对于全局索引:

    @DynamoDBIndexHashKey(globalSecondaryIndexName = INDEX_GLOBAL_RANGE_US_TS) @DynamoDBAttribute(attributeName = PROPERTY_USER) public String getUser() { return user; } 
  • 对于与全局索引相关的范围索引:

     @DynamoDBIndexRangeKey(globalSecondaryIndexName = INDEX_GLOBAL_RANGE_US_TS) @DynamoDBAttribute(attributeName = PROPERTY_TIMESTAMP) public String getTimestamp() { return timestamp; } 

此外,如果您通过全局索引读取表格,则必须是最终读取(不是一致的读取):

 queryExpression.setConsistentRead(false); 

另一种解释方法:LSI可以帮助您对具有相同散列键的项目执行附加查询。 GSI可以帮助您对“整个桌子”上的项目进行类似的查询。 所以非常有用。

如果您有用户个人资料表:unique-id,name,email。 在这里,如果你需要使名称,电子邮件表查询表 – 那么唯一的办法是让他们GSI(LSI不会帮助)

一种方法是这样的:

LSI – 允许您在单个哈希键上执行查询,同时使用多个不同的属性来“过滤”或限制查询。

GSI – 允许您对表中的多个哈希键执行查询,但是结果会导致吞吐量增加。

表格types的更广泛的细分以及它们如何工作,如下所示:

只有哈希

你可能已经知道了; 散列键本身必须是唯一的,因为写入已存在的散列键将覆盖现有数据。

哈希+范围

一个哈希键+范围键允许你有多个相同的哈希键,只要他们有一个不同的范围键。 在这种情况下,如果你写了一个已经存在的Hash-Key,但是使用了一个尚未被这个Hash-Key使用的Range-Key,它将产生一个新的项目,而如果一个项目具有相同的Hash + Range组合已经存在,它会覆盖匹配的项目。

另一种想法是像一个格式的文件。 只要格式(范围)不同,您可以在同一个文件夹(表格)中拥有与另一个文件相同名称(散列)的文件。 同样,只要名称不同,就可以有多个相同格式的文件。

LSI

LSI和Hash-Key + Range-Key基本相同,在创build项目时遵循相同的规则,除了还必须为LSI提供值外, 他们不能留空/空。

说一个LSI是“Range-Key 2”并不完全正确,因为你不能使用(使用我之前的文件和格式类比)一个名为file.format.lsifile.format.lsi2的文件。 但是,您可以使用file2.format.lsifile2.format.lsifile2.format.lsifile2.format.lsi

基本上,LSI只是一个“filter键”,而不是一个实际的范围键; 您的基础哈希和范围值组合必须仍然是唯一的,而LSI值不必是唯一的。 一个更简单的方法来看待它可能是将LSI视为文件中的数据。 您可以编写代码来查找名为“PROJECT101”的所有文件,而不pipe它们的fileFormat如何,然后读取里面的数据以确定查询中应该包含哪些内容以及什么被省略。 这基本上是LSI的工作原理(只是没有打开文件来读取其内容的额外开销)。

GSI

对于GSI,实质上是为每个GSI创build另一个表,但是没有维护在它们之间镜像数据的多个单独表的麻烦; 这就是为什么他们花费更多的吞吐量

因此,对于GSI,您可以指定fileName作为您的基本哈希键,并将fileFormat为您的基本范围键。 然后可以指定一个GSI,它具有fileName2的哈希键和fileFormat2的范围键。 然后你可以查询fileNamefileName2如果你喜欢,不像LSI,你只能在fileName查询。

主要的优点是你只需要维护一张表而不是2个,而且每次你​​写入主哈希/范围或GSI哈希/范围,其他的(s)也会自动更新,所以你不能像使用多表格设置那样“忘记”更新其他表格。 另外,更新一个之前和更新另一个之前没有连接丢失的机会,就像使用多表设置一样。

此外,GSI可以“重叠”基础的哈希/范围组合。 所以,如果你想用fileNamefileFormat作为你的基础Hash / Range和filePriorityfileName作为你的GSI,你可以。

最后,GSI哈希+范围组合不一定是唯一的,而基础哈希+范围组合必须是唯一的。 这是一个双/多表设置不可能的,但是与GSI。 因此,在更新时,您必须为基本和GSI哈希+范围提供值; 这些值都不能为空/空。

这个文件给出了很好的解释:

https://aws.amazon.com/blogs/aws/now-available-global-secondary-indexes-for-amazon-dynamodb/

我不能评论这个问题,但是在读写性能方面更好:

(本地索引,表读写吞吐量为100)或(全局索引读写吞吐量为50,表的读写吞吐量为50?)

我不需要单独的分区键为我的用例,所以本地索引应足以满足所需的function。

Interesting Posts