DynamoDB 中局部索引和全局索引的区别

我很好奇这两个次要索引以及它们之间的区别。很难想象这会是什么样子。我认为,这将帮助更多的人,而不仅仅是我。

90639 次浏览

本地辅助索引仍然依赖于原始的 Hash 键。 当提供具有 hash + range 的表时,可以将 LSI 看作 hash + range 1、 hash + range 2. . hash + range 6。 您可以查询另外5个范围属性。 而且,只有一个配置的吞吐量。

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

GSI 通告中可以找到关于这些差异的更详细的信息

另一种解释方法是: LSI 帮助您对具有相同 Hash 键的项执行其他查询。GSI 可以帮助您对“跨表”的项目进行类似的查询。非常有用。

如果您有一个用户配置文件表: 惟一标识,姓名,电子邮件。在这里,如果你需要使表可查询的名称,电子邮件-那么唯一的方法是使他们 GSI (LSI 不会帮助)

以下是按索引进行搜索的可能性:

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

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

全球和本地索引: 这些是在表上创建的“附加”索引,此外还有表的现有散列索引和范围索引。 全局索引 类似于散列。范围指数的行为类似于与表的散列一起使用的范围索引。 在代码中的实体模型中,getter 必须按以下方式注释:

  • 全球指数:

    @DynamoDBIndexHashKey(globalSecondaryIndexName = INDEX_GLOBAL_RANGE_US_TS)
    @DynamoDBAttribute(attributeName = PROPERTY_USER)
    public String getUser() {
    return user;
    }
    
  • For range index associated to the global index:

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

Besides, if you read a table by a Global index, it must be an Eventual read (not Consistent read):

queryExpression.setConsistentRead(false);

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

全局辅助索引 ーー具有散列和范围键的索引,可以 全局辅助索引与表中的索引不同 被认为是“全局的”,因为对索引的查询可以跨越 跨所有分区的表中的数据。

本地辅助索引 ー与 表,但是一个不同的范围键。本地辅助索引是“ local” 在这个意义上,本地辅助索引的每个分区都有作用域 到具有相同哈希键的表分区。

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

  • 吞吐量:

本地辅助索引消耗来自表的吞吐量。当通过本地索引查询记录时,操作将消耗表中的读取容量单位。在具有本地索引的表中执行写操作(创建、更新、删除)时,将有两个写操作,一个针对表,另一个针对索引。这两个操作都将消耗表中的写容量单位。

全局二级索引有它们自己的规定吞吐量,当你查询索引时,操作将消耗来自索引的读取能力,当你在一个有全局索引的表中执行写操作(创建、更新、删除)时,将有两个写操作,一个对表,另一个对索引 * 。

* 在界定全球二级指数的预定吞吐量时,确保特别注意以下要求:

为了使表写取得成功,需要提供的吞吐量 表及其所有全局辅助索引的设置必须 具有足够的写入容量以容纳写入; 否则,将引发 写入表将被节流。

  • 管理:

本地辅助索引只能在创建表时创建,无法将本地辅助索引添加到现有表中,创建索引后也无法删除它。

创建表并添加到现有表中时可以创建全局辅助索引,也允许删除现有的全局辅助索引。

  • 阅读一致性:

本地二级指数支持最终或强烈的一致性,而全球二级指数只支持最终一致性。

  • 投影:

本地辅助索引允许检索未投影到索引的属性(尽管附加成本: 性能和消耗的容量单位)。使用全局辅助索引,您只能检索投影到索引的属性。

特别考虑次级索引键的唯一性:

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

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

一种说法是:

LSI-允许您在单个 Hash-Key 上执行查询,同时使用多个不同的属性来“筛选”或限制查询。

GSI-允许您对一个表中的多个 Hash-Key 执行查询,但是由此导致吞吐量增加。

表格类型及其工作方式的详细分类如下:

只有散列

您可能已经知道,Hash-Key 本身必须是唯一的,因为写入已经存在的 Hash-Key 将覆盖现有数据。

散列 + 范围

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 只是一个“ Filter-key”,而不是一个实际的 Range-Key; 基本的 Hash 和 Range 值组合必须仍然是唯一的,而 LSI 值根本不必是唯一的。更简单的方法可能是将 LSI 视为文件中的数据。您可以编写代码来查找所有名为“ PROJECT101”的文件,而不管它们的 fileFormat是什么,然后读取其中的数据以确定查询中应该包含哪些内容以及忽略哪些内容。这基本上就是 LSI 的工作方式(只是没有打开文件读取其内容的额外开销)。

GSI

对于 GSI,您实际上是为每个 GSI 创建另一个表,但是不必维护多个独立的表来反映它们之间的数据; 这就是为什么它们的吞吐量更高的原因。

因此,对于 GSI,可以指定 fileName作为基础哈希键,指定 fileFormat作为基础 Range-Key。然后可以指定具有 fileName2的 Hash-Key 和 fileFormat2的 Range-Key 的 GSI。然后,您可以根据需要查询 fileNamefileName2,这与只能查询 fileName的 LSI 不同。

主要的好处是你只需要维护一个表,而不是2个,当你写入主哈希/范围或 GSI 哈希/范围时,其他表也会自动更新,所以你不能“忘记”更新其他表,就像你可以设置多表一样。另外,在更新一个连接和更新另一个连接之前,不会出现连接丢失的情况,就像多表设置那样。

此外,GSI 可以“重叠”基本散列/范围组合。因此,如果你想制作一个表,以 fileNamefileFormat作为基础散列/范围,以 filePriorityfileName作为 GSI,你可以。

最后,GSI Hash + Range 组合不必是唯一的,而基础 Hash + Range 组合必须是唯一的。这在双/多表设置中是不可能的,但在 GSI 中是可行的。因此,在更新时,必须同时为基 AND GSI Hash + Range 提供值; 这些值都不能为空/空。

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

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

我不能对这个问题作出评论,但就写作和阅读性能而言,哪一个更好:

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

对于我的用例,我不需要单独的分区键,因此本地索引应该足以满足所需的功能。

GSI 不能用于一致的读取。

LSI 可以用于一致的读取,但是它们将主分区大小限制为10GB。此外,只能在创建表时创建 LSI。