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