DynamoDB - 我需要多个 GSI 吗?
DynamoDB - Do I need multiple GSIs?
我的应用程序只有一个 table 设计。但是,table 中的某些行包含我计划用于查询不同类型数据的重要信息。让我解释。我的应用程序处理用户触发的警报。当警报被触发时,我会记录很多关于该警报的信息。我的目标是创建 GSI,以便我可以检索和排序有关已触发警报的所有信息。让我举一个例子,我的 table.
中的一行
PK
SK
GSI1PK
GSI1SK
GSI2PK
GSI2SK
GSI3PK
GSI3SK
GSI4PK
GSI4SK
GSI5PK
GSI5SK
OtherProperties
ShipmentReceived
AL#TR#2020-08-19T23:37:41.513Z
AL#TR
2020-08-19T23:37:41.513Z
AL#TR#LO
Building1#WingA#Floor1#OfficeB#2020-08-19T23:37:41.513Z
user@example.com
2020-08-19T23:37:41.513Z
1234567
2020-08-19T23:37:41.513Z
AL#TR#HOW
PC#KS
Other values go in other columns
注意:AL#TR 表示:“触发警报”,AL#TR#LO 表示“从位置触发警报”。 AL#TR#HOW 表示警报是如何触发的。 1234567是用于触发警报的“设备ID”。
这种结构让我可以查询各种有趣的数据。例如:
- 所有按日期排序的 ShipmentReceived 警报
- GSI1:我可以获取公司触发的所有警报并按日期对它们进行排序(包括 ShipmentReceived、PackageSent 等)
- GSI2:我可以获得在特定位置触发的所有警报,并且可以按日期对它们进行排序。
- GSI3:我可以获得特定用户触发的所有警报,并且可以按日期排序。
- GSI4:我可以获得特定设备触发的所有警报,并且可以按日期对它们进行排序。
- GSI5:允许我按触发警报的方法对警报进行排序。
我正在阅读 DynamoDB documentation,我看到它说不建议对不经常查询的项目使用索引。许多这些 GSI 根本不会被经常查询。只是偶尔。
我的问题是,我创建 5 个不同的 GSI 是不是做错了?在这种情况下?有没有更好的方法来模拟这些数据?我想到了这一点,也许我可以插入多行相关信息,而不是将所有内容都放在一行中,但我不知道这是否是更好的方法。还有其他想法吗?
我在西雅图的 DynamoDB 团队工作,此回复来自我的一位同事:
“任何时候您需要对相同的实体进行不同的分组或排序,您都需要为该访问模式创建一个新的 GSI。当您将多个实体类型存储在同一个 table 中时,您可以重用 GSI (又名 GSI 重载)针对不同实体上的那些访问模式。但在您的情况下,所有访问模式都是关于对警报实体进行分组和排序,因此每个实体都需要不同的 GSI。
“然而,GSI 的存在是为了加速或降低读取请求的成本,但代价是更高的写入开销(以保持 GSI 更新)。这在具有高 read:write 比率以及响应必须快速返回的位置。但是对于不经常执行且没有低延迟要求的读取访问模式,与拥有一个成本相比,简单地执行扫描操作可能更便宜GSI。例如,对于每天或每周运行一次的批处理作业,每天或每周扫描一次 table 可能更便宜。”
我的应用程序只有一个 table 设计。但是,table 中的某些行包含我计划用于查询不同类型数据的重要信息。让我解释。我的应用程序处理用户触发的警报。当警报被触发时,我会记录很多关于该警报的信息。我的目标是创建 GSI,以便我可以检索和排序有关已触发警报的所有信息。让我举一个例子,我的 table.
中的一行PK | SK | GSI1PK | GSI1SK | GSI2PK | GSI2SK | GSI3PK | GSI3SK | GSI4PK | GSI4SK | GSI5PK | GSI5SK | OtherProperties |
---|---|---|---|---|---|---|---|---|---|---|---|---|
ShipmentReceived | AL#TR#2020-08-19T23:37:41.513Z | AL#TR | 2020-08-19T23:37:41.513Z | AL#TR#LO | Building1#WingA#Floor1#OfficeB#2020-08-19T23:37:41.513Z | user@example.com | 2020-08-19T23:37:41.513Z | 1234567 | 2020-08-19T23:37:41.513Z | AL#TR#HOW | PC#KS | Other values go in other columns |
注意:AL#TR 表示:“触发警报”,AL#TR#LO 表示“从位置触发警报”。 AL#TR#HOW 表示警报是如何触发的。 1234567是用于触发警报的“设备ID”。
这种结构让我可以查询各种有趣的数据。例如:
- 所有按日期排序的 ShipmentReceived 警报
- GSI1:我可以获取公司触发的所有警报并按日期对它们进行排序(包括 ShipmentReceived、PackageSent 等)
- GSI2:我可以获得在特定位置触发的所有警报,并且可以按日期对它们进行排序。
- GSI3:我可以获得特定用户触发的所有警报,并且可以按日期排序。
- GSI4:我可以获得特定设备触发的所有警报,并且可以按日期对它们进行排序。
- GSI5:允许我按触发警报的方法对警报进行排序。
我正在阅读 DynamoDB documentation,我看到它说不建议对不经常查询的项目使用索引。许多这些 GSI 根本不会被经常查询。只是偶尔。
我的问题是,我创建 5 个不同的 GSI 是不是做错了?在这种情况下?有没有更好的方法来模拟这些数据?我想到了这一点,也许我可以插入多行相关信息,而不是将所有内容都放在一行中,但我不知道这是否是更好的方法。还有其他想法吗?
我在西雅图的 DynamoDB 团队工作,此回复来自我的一位同事:
“任何时候您需要对相同的实体进行不同的分组或排序,您都需要为该访问模式创建一个新的 GSI。当您将多个实体类型存储在同一个 table 中时,您可以重用 GSI (又名 GSI 重载)针对不同实体上的那些访问模式。但在您的情况下,所有访问模式都是关于对警报实体进行分组和排序,因此每个实体都需要不同的 GSI。
“然而,GSI 的存在是为了加速或降低读取请求的成本,但代价是更高的写入开销(以保持 GSI 更新)。这在具有高 read:write 比率以及响应必须快速返回的位置。但是对于不经常执行且没有低延迟要求的读取访问模式,与拥有一个成本相比,简单地执行扫描操作可能更便宜GSI。例如,对于每天或每周运行一次的批处理作业,每天或每周扫描一次 table 可能更便宜。”