全局与DynamoDB中的本地二级索引

时间:2018-04-28 22:03:23

标签: indexing amazon-dynamodb

我仍然对使用本地二级索引感到困惑。当需要LSI和GSI时,请给我具体的用例。

例如,这里是" GenreAlbumTitle"索引应该是GSI还是LSI?https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.CoreComponents.html#HowItWorks.CoreComponents.PrimaryKey

我似乎无法满足需要LSI的需求,因为我需要的任何索引都将覆盖表的整行,而不仅仅是针对一个分区。如果有人也可以触及成本方面因为我了解LSI更便宜(但为什么它更便宜)?

谢谢大家!

2 个答案:

答案 0 :(得分:10)

Dynamo中的每个项目都必须具有唯一的主键。主键是基表索引。主键必须具有分区键,并且可以选择使用范围键(也称为排序键)。在分区内,项目按范围键排序。使用分区键访问项目很快。

辅助索引允许您使用备用密钥查询表。 本地二级索引(LSI)与主键(索引)具有相同的分区键,但具有不同的范围键。考虑LSI的方法是它与主索引(键)的数据相同,只是按不同的属性排序。

全局二级索引(GSI)具有与主键不同的分区键,因此是一组不同的数据。

LSI和GSI之间的一个重要区别是 LSI从基表中获取其吞吐量,其中您分别购买了GSI吞吐量。换句话说,LSI不需要任何费用,而GSI会产生额外的成本。

让我们看一下Music表示例。让我们说基表有这个模式;

Artist: (Primary Key) Partition Key
SongTitle: (Primary Key) Range Key
AlbumTitle:
DateOfRelease:

此表是歌曲列表。我可以非常有效地访问艺术家的所有歌曲(即艺术家使用分区键查询)。当我进行此查询时,歌曲将由SongTitle订购。我还可以使用唯一的主键非常有效地访问Artist和SongTitle的歌曲。

现在假设我想获得艺术家的所有歌曲,但是由DateOfRelease订购。在当前架构中,我需要获取所有歌曲,然后在我的应用程序中对它们进行排序。一个很好的选择是使用Artist的分区键和范围键DateOfRelease创建一个新索引。这将是LSI,因为索引(Artist)的分区键与主键的分区键相同。我不需要购买额外的吞吐量容量,因为该索引将从基表容量中自行配置。

现在假设我想通过SongTitle订购的AlbumTitle来访问歌曲,即创建专辑列表。为了有效地执行此操作,我使用分区键AlbumTitle和范围键SongTitle创建一个新索引。这是一个GSI,因为分区键与主键不同。此GSI必须单独配置到基表,因此需要额外费用。

在回答您的问题时,GenreAlbumTitle是一个GSI,因为它有一个与Music不同的分区键。

答案 1 :(得分:4)

对于使用 LSI 的成本存在一些误解,所以让我在这里澄清一下。

使用 LSI 不是免费的。就像 GSI 一样,dynamoDB 需要创建和维护表的额外部分副本,以便快速获取结果。这种额外副本的维护将产生与 GSI 相同的额外读取、写入和存储成本。 (额外费用将以粗体显示)。唯一的区别是,您使用与主表相同的薪酬计划,而不是分配单独的薪酬计划。

在讨论额外成本之前,让我再次总结一下部分副本表中存储了什么样的信息。部分表副本 (LSI) 包含分区键(与原始表相同)、排序键(与原始表不同)以及任何其他投影属性。

原始表格

<头>
艺术家(主键) 歌曲名称(排序键) 专辑名称 发布日期
迈克尔杰克逊 击败它 惊悚 1982 年 12 月 1 日
周末 山丘 疯狂背后的美丽 2015 年 5 月 27 日

LSI

<头>
艺术家(主键) 专辑名称(排序键) 发布日期
迈克尔杰克逊 惊悚 1982 年 12 月 1 日
周末 疯狂背后的美丽 2015 年 5 月 27 日,

投影属性是我们要从 LSI 查询的附加信息。我可以说,“按专辑名称显示 Weeknd 专辑的所有发行日期”。如您所见,我们不关心这里的歌曲名称,也不包含在我们的 LSI 预测中。

读取的额外费用

  • 对于单独使用 LSI 表即可满足的查询,您需要支付 1 个读取单位的费用。示例:“按专辑名称显示 Weeknd 歌曲的所有发行日期。”

  • 对于 LSI 不知道如何自行处理的查询,您需要支付 1 个额外的读取单元,迫使它转到主表寻求帮助。这将总共花费 2 个读取单元。示例:“显示所有发行日期和 Weeknd 歌曲的歌曲名称,按专辑名称排序。”

写入的额外成本

(写入主表,有自己的写入成本,更改稍后传播到 LSI)

  • 如果对主表的更新导致在 LSI 中创建一个新行 => 1 个额外的写入单元
  • 如果更新主表导致 LSI 中现有行的关键属性被更新 => 删除成本(1 个单位)+ 创建(1 个单位)= 2 个额外的写入单位
  • 如果对主表的更新导致 LSI 中现有行的非键属性被更新 => 1 个额外的写入单元
  • 如果对主表的更新导致 LSI 中现有行的现有属性被删除 => 1 个额外的写入单元
  • 如果对主表的更新没有改变 LSI 的任何行 => 0 个额外的写入单元

额外的存储费用

  • 您为以下项目支付额外费用:(索引键的大小 + 投影属性的大小 + 开销)x 行数

如您所见,如果我们对 LSI 不小心,额外的成本可能会变得过高。为了最大限度地降低成本,您必须:

  • 仔细考虑您的典型查询。您需要哪些类型的信息?
  • 读取成本和存储成本之间存在权衡。如果将每个属性都投影到 LSI,则不会产生额外的读取成本,但存储成本会翻倍。如果您只投影关键属性,并且经常获取关键属性以外的其他信息,则必须返回主表寻求帮助会产生大量额外的读取成本。
  • 对于大量写入的表,预计会导致写入成本大幅上升。请记住,如果对主表的更新更新了 LSI 中某个项目的关键属性,则您需要额外支付 2 个写入单位,对于非关键属性,则需要额外支付 1 个写入单位。