我很好奇这两个二级索引以及它们之间的差异。很难想象这是什么样子。而且我认为,这将帮助更多的人,而不仅仅是我。
7 回答
本地二级索引仍然依赖于原始的 Hash Key。当您提供带有 hash+range 的表时,请将 LSI 视为 hash+range1、hash+range2.. hash+range6。您还有 5 个范围属性可供查询。此外,只有一个预置吞吐量。
全局二级索引定义了一个新的范例——每个索引有不同的哈希/范围键。
这打破了每个表一个哈希键的原始用法。这也是为什么在定义 GSI 时需要为每个索引添加预配置吞吐量并为此付费的原因。
有关差异的更多详细信息,请参阅GSI 公告
这是文档中的正式定义:
全局二级索引——具有哈希和范围键的索引,可以与表上的不同。全局二级索引被认为是“全局的”,因为对索引的查询可以跨越表中的所有数据,跨越所有分区。
本地二级索引——与表具有相同哈希键但范围键不同的索引。本地二级索引是“本地的”,因为本地二级索引的每个分区都被限定为具有相同哈希键的表分区。
然而,就关键定义而言,差异远远超出了可能性。找出以下将直接影响维护索引的成本和工作量的一些重要因素:
- 吞吐量:
本地二级索引消耗表中的吞吐量。当您通过本地索引查询记录时,该操作会消耗表中的读取容量单位。当您在具有本地索引的表中执行写操作(创建、更新、删除)时,将有两个写操作,一个针对表,另一个针对索引。这两个操作都将消耗表中的写入容量单位。
全局二级索引有自己的预置吞吐量,当您查询索引时,该操作将消耗索引的读取容量,当您在具有全局索引的表中执行写入操作(创建、更新、删除)时,将有两个写操作,一个用于表,另一个用于索引*。
*在定义全局二级索引的预置吞吐量时,请务必特别注意以下要求:
为了使表写入成功,表的预置吞吐量设置及其所有全局二级索引必须具有足够的写入容量来容纳写入;否则,对表的写入将受到限制。
- 管理 :
本地二级索引只能在创建表时创建,无法将本地二级索引添加到现有表中,而且一旦创建索引就无法删除它。
可以在创建表时创建全局二级索引并将其添加到现有表中,也允许删除现有的全局二级索引。
- 读取一致性:
本地二级索引支持最终一致性或强一致性,而全局二级索引仅支持最终一致性。
- 投影:
本地二级索引允许检索未投影到索引的属性(尽管有额外的成本:性能和消耗的容量单位)。使用全局二级索引,您只能检索投影到索引的属性。
关于二级索引定义的键的唯一性的特殊考虑:
在本地二级索引中,范围键值对于给定的哈希键值不需要是唯一的,同样适用于全局二级索引,键值(哈希和范围)不需要是唯一的。
资料来源:http ://docs.aws.amazon.com/amazondynamodb/latest/developerguide/SecondaryIndexes.html
这些是可能的索引搜索:
- 通过哈希
- 按哈希 + 范围
- 按哈希 + 本地索引
- 按全球指数
- 按全局索引 + 范围索引
表的哈希和范围索引: 这些是以前版本的 Amazon AWS 开发工具包的常用索引。
全局和本地索引: 这些是在表上创建的“附加”索引,除了表的现有哈希和范围索引。 全局索引类似于哈希。范围索引的行为类似于与表的哈希一起使用的范围索引。在代码中的实体模型中,必须以这种方式注释 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 - 允许您对单个 Hash-Key 执行查询,同时使用多个不同的属性来“过滤”或限制查询。
GSI - 允许您对表中的多个 Hash-Key 执行查询,但因此会增加吞吐量。
下面对表格类型及其工作方式进行了更广泛的细分:
仅散列
你可能已经知道了;Hash-Key 本身必须是唯一的,因为写入已经存在的 Hash-Key 会覆盖现有数据。
哈希+范围
Hash-Key + Range-Key 允许您拥有多个相同的 Hash Key,只要它们具有不同的范围键即可。在这种情况下,如果您写入已存在的 Hash-Key,但使用该 Hash-Key 尚未使用的 Range-Key,则会创建一个新项目,而如果项目具有相同的 Hash+Range 组合已经存在,它会覆盖匹配的项目。
另一种思考方式就像一个具有格式的文件。您可以在同一个文件夹(表)中拥有与另一个文件同名(哈希)的文件,只要它们的格式(范围)不同。同样,您可以拥有多个相同格式的文件,只要它们的名称不同。
大规模集成电路
LSI 与 Hash-Key + Range-Key 基本相同,并且在创建项目时遵循相同的规则,除了您还必须为 LSI 提供值;它们不能留空/空。
说 LSI 是“Range-Key 2”并不完全正确,因为您不能拥有(使用我之前的文件和格式类比)名为:file.format.lsi
和file.format.lsi2
. 但是,您可以拥有file.format.lsi
andfile.format2.lsi
或file.format.lsi
and file2.format.lsi
。
基本上,LSI 只是一个“Filter-key”,而不是实际的 Range-Key;您的基本 Hash 和 Range 值组合必须仍然是唯一的,而 LSI 值根本不必是唯一的。一种更简单的看待它的方法可能是将 LSI 视为文件中的数据。您可以编写代码来查找名称为“PROJECT101”的所有文件,而不管它们fileFormat
的 . 这基本上就是 LSI 的工作方式(只是没有打开文件以读取其内容的额外开销)。
GSI
对于 GSI,您实际上是在为每个 GSI 创建另一个表,但无需维护多个在它们之间镜像数据的单独表;这就是为什么它们花费更多吞吐量的原因。
因此,对于 GSI,您可以指定fileName
基本 Hash-Key 和fileFormat
基本 Range-Key。然后,您可以指定具有 Hash-KeyfileName2
和 Range-Key 的GSI fileFormat2
。然后,您可以查询其中一个fileName
或fileName2
如果您愿意,与 LSI 不同,您只能查询fileName
.
主要优点是您只需要维护一个表,而不是 2 个,并且每当您写入主哈希/范围或 GSI 哈希/范围时,其他的也将自动更新,所以你不能像使用多表设置一样“忘记”更新其他表。此外,在更新一个之后和更新另一个之前,没有机会丢失连接,就像多表设置一样。
此外,GSI 可以“重叠”基本 Hash/Range 组合。因此,如果您想制作一个表格,fileName
并将fileFormat
其作为您的基本哈希/范围,filePriority
并将fileName
其作为您的 GSI,您可以。
最后,GSI Hash+Range 组合不必是唯一的,而基本 Hash+Range 组合必须是唯一的。这在双/多表设置中是不可能的,但在 GSI 中是不可能的。因此,您必须在更新时同时提供基础和 GSI 哈希+范围的值;这些值都不能为空/null。
另一种解释方式:LSI 帮助您对具有相同 Hash Key 的项目进行额外查询。GSI 可帮助您对“整个表格”的项目进行类似的查询。所以非常有用。
如果您有一个用户配置文件表:唯一 ID、姓名、电子邮件。在这里,如果您需要在名称、电子邮件上使表格可查询 - 那么唯一的方法就是让它们成为 GSI(LSI 不会有帮助)
该文档给出了很好的解释:
https://aws.amazon.com/blogs/aws/now-available-global-secondary-indexes-for-amazon-dynamodb/
我无法评论这个问题,但在读写性能方面哪个更好:
(表读写吞吐量为 100 的本地索引)或(读/写吞吐量为 50 且表的读/写吞吐量为 50 的全局索引?)
我的用例不需要单独的分区键,因此本地索引应该足以满足所需的功能。
GSI 不能用于一致性读取。
LSI 可用于一致性读取,但它们会将主分区大小限制为 10GB。LSI 也只能在创建表时创建。