DynamoDB中的本地和全局索引之间的差异

Mic*_*lko 109 indexing amazon-dynamodb secondary-indexes

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

Che*_*rel 97

本地二级索引仍然依赖于原始的Hash密钥.当您提供具有散列+范围的表时,请将LSI视为散列+ range1,散列+ range2 ..散列+ range6.您还可以再查询5个范围属性.此外,只有一个预配置吞吐量.

全局二级索引定义了一个新范例 - 每个索引的不同哈希/范围键.
这打破了每个表的一个散列键的原始用法.这也是定义GSI时需要为每个索引添加预配置吞吐量并为其付费的原因.

有关差异的更多详细信息可在GSI公告中找到

  • 可能会增加1)二级索引,无论是LSI还是GSI,与唯一性无关 (2认同)
  • 您最多可以拥有 5 个本地二级索引,这就是为什么 Chen Harel 说_“您还有 5 个范围属性可供查询”_。 (2认同)

bsd*_*bsd 74

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

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

本地二级索引 - 与表具有相同散列键但具有不同范围键的索引.本地二级索引是"本地"的,因为本地二级索引的每个分区都限定为具有相同散列键的表分区.

但是,这些差异远远超出了关键定义的可能性.在下面找到一些重要因素,这些因素将直接影响维护索引的成本和工作量:

  • 吞吐量:

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

全局二级索引具有自己的预配置吞吐量,当您查询索引时操作将消耗索引的读取容量,当您在具有全局索引的表中执行写入操作(创建,更新,删除)时,将有两个写操作,一个用于表另一个用于索引*.

*在定义全球二级索引的预配置吞吐量时,请确保特别注意以下要求:

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

  • 管理层:

只能在创建表时创建本地二级索引,无法将本地二级索引添加到现有表,一旦创建了无法删除它的索引.

创建表并添加到现有表时,可以创建全局二级索引,也允许删除现有的全局二级索引.

  • 读一致性:

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

  • 投影:

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

关于二级指标定义的唯一性的特殊考虑:

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

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

  • @bsd 添加关于使用 LSI 所施加的一个主要限制的注释是有意义的:“对于具有本地二级索引的表,每个分区键值有 10 GB 的大小限制。具有本地二级索引的表可以存储任何项目数,只要任何一个分区键值的总大小不超过 10 GB。” (https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LSI.html#LSI.Creating) (2认同)

Car*_* AG 27

这些是索引可能的搜索:

  • 哈希
  • 通过Hash + Range
  • 通过哈希+本地指数
  • 按全球指数
  • 按全球指数+范围指数

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

全局索引和本地索引: 这些是在表上创建的"附加"索引,以及表的现有散列和范围索引. 全局索引类似于哈希.范围索引的行为类似于与表的哈希一起使用的范围索引.在代码中的实体模型中,必须以这种方式注释getter:

  • 对于全局索引:

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

    @DynamoDBIndexRangeKey(globalSecondaryIndexName = INDEX_GLOBAL_RANGE_US_TS)
    @DynamoDBAttribute(attributeName = PROPERTY_TIMESTAMP)
    public String getTimestamp() {
        return timestamp;
    }
    
    Run Code Online (Sandbox Code Playgroud)

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

queryExpression.setConsistentRead(false);
Run Code Online (Sandbox Code Playgroud)


DGo*_*erg 18

一种说法是:

LSI - 允许您在单个Hash-Key上执行查询,同时使用多个不同的属性来"过滤"或限制查询.

GSI - 允许您对表中的多个哈希密钥执行查询,但结果会导致额外的吞吐量.

下表更广泛地分析了表格类型及其工作原理:

只有哈希

你可能已经知道了; 哈希密钥本身必须是唯一的,因为写入已存在的哈希密钥将覆盖现有数据.

哈希+范围

Hash-Key + Range-Key允许您拥有多个相同的Hash密钥,只要它们具有不同的范围密钥即可.在这种情况下,如果您写入已经存在的Hash-Key,但是使用该Hash-Key尚未使用的Range-Key,则会生成一个新项目,而如果一个具有相同Hash + Range组合的项目已存在,它会覆盖匹配项.

另一种思考方式就像是带有格式的文件.只要格式(范围)不同,您就可以在同一文件夹(表)中拥有与另一个文件具有相同名称(哈希)的文件.同样,只要名称不同,您就可以拥有相同格式的多个文件.

LSI

LSI基本上与Hash-Key + Range-Key相同,并且在创建项目时遵循与其相同的规则,除了您还必须为LSI提供值之外; 它们不能留空/ null.

要说LSI是"Range-Key 2"并不完全正确,因为你不能拥有(使用我之前的文件和格式)类似的文件:file.format.lsifile.format.lsi2.你可以,但是,必须file.format.lsifile.format2.lsifile.format.lsifile2.format.lsi.

基本上,LSI只是一个"过滤键",而不是一个实际的Range-Key; 您的基础哈希值和范围值组合必须仍然是唯一的,而LSI值根本不必是唯一的.查看它的更简单方法可能是将LSI视为文件中的数据.您可以编写代码,找到名为"PROJECT101"的所有文件,无论它们是什么fileFormat,然后读取内部数据以确定查询中应包含的内容以及省略的内容.这基本上就是LSI的工作原理(只是没有打开文件来读取其内容的额外开销).

GSI

对于GSI,您实际上是为每个GSI创建另一个表,但没有维护多个单独的表来反映它们之间的数据的麻烦; 这就是他们花费更多吞吐量的原因.

因此,对于GSI,您可以指定fileName基础Hash-Key和fileFormat基本Range-Key.然后,您可以指定具有Hash-Key fileName2和Range-Key的GSI fileFormat2.然后,您可以在任何一个fileNamefileName2如果您喜欢的情况下进行查询,这与您只能查询的LSI不同fileName.

主要优点是您只需要维护一个表而不是2个,并且无论何时写入主哈希/范围或GSI哈希/范围,其他(s)也会自动更新,所以你不能"忘记"使用多表设置更新其他表格.此外,更新一个之后和更新另一个之前没有连接丢失的可能性,就像多表设置一样.

另外,GSI可以"重叠"基础哈希/范围组合.所以,如果你想使一个表fileName,并fileFormat为你的基地哈希/范围,并filePriorityfileName为您的GSI,就可以了.

最后,GSI哈希+范围组合不必是唯一的,而基本哈希+范围组合必须是唯一的.这是双/多表设置无法实现的,但与GSI一起使用.因此,在更新时,您必须为基本和GSI哈希+范围提供值; 这些值都不能为空/ null.


Son*_*van 12

另一种解释方法:LSI可以帮助您对具有相同哈希键的项目执行其他查询.GSI可以帮助您对"跨表"的项目执行类似的查询.非常有用.

如果您有用户配置文件表:unique-id,name,email.在这里,如果你需要使表可查询的名称,电子邮件 - 那么唯一的方法是让他们GSI(LSI不会帮助)

  • 您能详细说明为什么只能通过 GSI 做到这一点吗? (2认同)