我们可以避免在 dynamodb 中进行扫描吗

Posted

技术标签:

【中文标题】我们可以避免在 dynamodb 中进行扫描吗【英文标题】:Can we avoid scan in dynamodb 【发布时间】:2018-12-01 08:50:42 【问题描述】:

我是 noSQL 数据建模的新手,所以如果我的问题是微不足道的,请见谅。我在 dynamodb 中找到的一个建议是在查询时始终提供“PartitionId”,否则它将扫描整个表。但是在某些情况下,我们需要列出我们的项目,例如在电子商务网站的情况下,我们需要在列表页面上列出我们的产品(带有分页)。

我们应该如何通过避免扫描或使用有效的方式来执行此列表?

【问题讨论】:

这是一个非常广泛的问题。有很多方法可以做到这一点。这一切都取决于您的表设计和索引的有效使用。起初,它可能看起来很像仅使用单个键的键值存储,但有很多方法可以改进它。我的建议阅读最佳实践 10 次 :) 我做了 docs.aws.amazon.com/amazondynamodb/latest/developerguide/… 【参考方案1】:

基本上有three ways of reading data from DynamoDB:

GetItem – 从表中检索单个项目。这是读取单个项目的最有效方式,因为它提供对项目物理位置的直接访问。 Query – 检索所有具有特定分区键的项目。在这些项目中,您可以将条件应用于排序键并仅检索数据的子集。查询提供对存储数据的分区的快速、高效访问。 Scan – 检索指定表中的所有项目。 (此操作不应该用于大型表,因为它会消耗大量系统资源。

就是这样。如您所见,您应该始终更喜欢 GetItem (BatchGetItem) 而不是 QueryQuery — 而不是 Scan

如果您将sort key 添加到您的数据中,您可以使用查询。 IE。您可以使用类别作为哈希键和产品名称作为排序键,以便显示特定类别项目的页面可以使用该类别和产品名称的查询。但是这种设计是脆弱的,因为您可能需要其他页面的其他键,例如,如果用户寻找特定的手机,您可能需要供应商+价格查询。 Indexes 可以在这里提供帮助,但他们有自己的权衡和 limitations。

此外,在query / scan 操作完成之后但在您获得结果之前应用任意表达式过滤,因此您需要为整个查询/扫描付费。这就像在应用程序中而不是在数据库端过滤数据一样。

我会说 DynamoDB 并不适用于多种工作负载。可能,它也不适合您的情况。将其视为丰富的键值(键到对象)存储,而不是“经典”RDBMS,其中索引成本更低、限制更少,并为开发人员提供丰富的查询功能。

有一个good article 描述了 DynamoDB 的潜在问题,请查看。它包含一个很棒的决策树,可以指导您完成 DynamoDB 论证。我贴在这里,但是请注意,原作者是ForrestBrazeal。

Another article值得一读。

最后,在 SO 上查看 this short answer,了解 DynamoDB 用例和问题。

附:进行扫描并没有犯罪(实际上我在我的一个项目中每天按计划进行一次),但这是一个例外情况,我对在这种情况下使用 DynamoDB 的决定感到遗憾。它在速度、金钱、支持和“肮脏”方面效率不高。我必须在工作之前增加容量并在工作之后减少它,但这是另一回事......

【讨论】:

+1 很好的解释,这不仅适用于 dynamodb,也适用于其他 nosql (documentdb)。如果您需要显示来自多个分片的数据(当未提供分区键时),它总是会导致扫描。这是否意味着,在列出多个项目时,我们应该形成不同的策略。例如,博客是使用 nosql 的一个很好的例子。所有的cmets,比如ect(属于一个博客)都可以一起存储在一个文档中(在一些nosql里面)。但是如何显示博客列表(只有博客和标题)?

以上是关于我们可以避免在 dynamodb 中进行扫描吗的主要内容,如果未能解决你的问题,请参考以下文章

Dynamodb 的清除技术

我们可以通过 AWS SDK 使用 GSI 删除 DynamoDB 中的项目吗?

对映射的DynamoDb数据进行Elasticsearch嵌套查询不返回任何内容

我们可以同时查询和删除 Amazon DynamoDB 中的项目吗?

如何使用 nodejs 使用 Dynamodb 并行扫描检索数据

AWS SDK JavaScript v3 / 如何在 dynamoDB 扫描命令中使用 ExpressionAttributeNames?