Amazon DynamoDB
开发人员指南 (API 版本 2012-08-10)
AWS 文档中描述的 AWS 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 Amazon AWS 入门

针对查询和扫描数据的最佳实践

本节介绍在 Amazon DynamoDB 中使用 QueryScan 操作的一些最佳实践。

扫描的性能注意事项

一般来说,在 DynamoDB 中,Scan 操作的效率低于其他操作。Scan 操作始终扫描整个表或二级索引。之后,它筛选出值以提供所需结果,从本质上讲,这增加了从结果集中删除数据这个额外步骤。

如有可能,应避免对大型表或索引使用带有会删除很多结果的筛选条件的 Scan 操作。同时,随着表或索引的增大,Scan 操作的速度会变慢。Scan 操作根据请求的值检查每个项目,可以在单次操作中用尽大型表或索引的预置吞吐量。为了缩短响应时间,请对表和索引进行设计,以便应用程序可以使用 Query 而非 Scan。(对于表,还可以考虑使用 GetItemBatchGetItem API。)

或者,如果要在应用程序设计中使用 Scan 操作,应最大程度地降低这一操作对您的请求率的影响。

避免读取活动陡增

创建表时,您要设置读取和写入容量单位要求。读取容量单位通过每秒强一致性 4 KB 数据读取请求的数量表示。一个最终一致性读取容量单位是每秒 2 个 4 KB 读取请求。默认情况下,Scan 操作执行最终一致性读取,可返回最多 1 MB(一页)数据。因此,单个 Scan 请求可占用 (1 MB 页面大小/4 KB 项目大小) /2 (最终一致性读取) = 128 个读取操作。如果改为请求强一致性读取,则 Scan 操作占用的吞吐量是预置吞吐量的两倍 - 256 次读取操作。

这表示相较于为表配置的读取容量,使用量陡增。这种由扫描引起的扫描占用容量单位的使用情况会阻止同一表的其他可能更为重要的请求使用可用的容量单位。因此,这些请求可能会造成 ProvisionedThroughputExceeded 异常。

问题不仅仅在于 Scan 使用的容量单位陡增。由于扫描请求的读取项目在分区中彼此相邻,因此扫描还可能会占用同一分区中的所有容量单位。这意味着,请求一直调用相同的分区,导致该分区的所有容量单位用尽,进而限制该分区中的其他请求。如果读取数据请求分布在多个分区之中,则此操作不会给特定分区带来限制。

下图说明了 QueryScan 操作引起的容量单位使用量陡增所带来的影响,以及这种情况对同一表的其他请求所造成的影响。

 4 种不同的场景,其中在表中显示预置吞吐量间隔、请求以及好结果和坏结果。

如此处所示,使用峰值会为表的预置吞吐量带来几个方面的影响:

  1. 好:请求和大小均匀分布

  2. 没那么好:频繁请求突发

  3. 差:一些随机大型请求

  4. 差:大型扫描操作

您可以使用以下技巧最大程度地减小扫描操作对表的预置吞吐量的影响,而不使用消耗大量资源的 Scan 操作。

  • 减小页面大小

    由于扫描操作会读取整个页面(默认情况下为 1 MB),因此,您可以通过设置较小的页面大小来降低扫描操作的影响。您可以使用 Scan 操作提供的 Limit 参数设置请求的页面大小。设置了较小的页面大小后,每个 QueryScan 请求都会使用更少的读取操作,并会在每个请求之间“停顿”。例如,假设每个项目为 4 KB,并且您将页面大小设置为 40 个项目。之后,Query 请求仅使用 20 次最终一致性读取操作或 40 次强一致性读取操作。如果占用较小容量单位的 QueryScan 操作数量较多,您就可以成功完成其他重要请求而不会受到限制。

  • 隔离扫描操作

    DynamoDB 旨在实现轻松可扩展性。因此,应用程序可以创建多个表以彼此区分,甚至多个表可能会复制彼此的内容。您可能会在没有“关键任务型”流量的表中执行扫描。某些应用程序会每小时在两个表 (一个用于关键流量,一个用于计账) 之间轮换流量来处理此负载。其他应用程序可通过让每次写入都在两个表(“关键任务型”表和“影子”表)中执行来实现这一目的。

将应用程序配置为重试接收响应代码 (指示已超出预置吞吐量) 的任何请求。或者,使用 UpdateTable 操作增加表的预置吞吐量。如果您的工作负载临时达到峰值,导致吞吐量偶然超出预置级别,请使用指数回退重试请求。有关实施指数回退的更多信息,请参阅错误重试和指数退避

利用并行扫描

很多应用程序都可以从使用并行 Scan 操作(而非按顺序扫描)中获益。例如,如果要处理含有历史数据的大型表,应用程序并行扫描比按顺序扫描速度快得多。后台“清理程序”进程中的多个工作线程可以对优先级比较低的表进行扫描,而不影响生产流量。在每个示例中,并行 Scan 的使用并不会限制其他应用程序的预置吞吐量资源。

尽管并行扫描比较有利,但是它可能会需要大量预置吞吐量。借助并行扫描,您的应用程序将具有多个工作线程,这些工作线程都同时运行 Scan 操作。这会快速占用表的所有预置读取容量。在这种情况下,需要访问此表的其他应用程序就有可能受到限制。

如果满足以下条件,就可以选择并行扫描:

  • 表的大小为 20 GB 或更大。

  • 表的预置读取吞吐量尚未完全利用。

  • 按顺序执行的 Scan 操作速度过慢。

选择 TotalSegments

TotalSegments 的最佳设置取决于您的具体数据、表的预置吞吐量设置和您对性能的要求。可能需要实验才能得到正确设置。我们建议您使用简单比率(例如每 2 GB 数据一个段)开始尝试。例如,对于 30 GB 的表,您可以将 TotalSegments 设置为 15 (30 GB / 2 GB)。之后,应用程序将使用 15 个工作线程,每个工作线程扫描不同的分段。

您也可以为基于客户端资源的 TotalSegments 选择一个值。可以将 TotalSegments 设置为 1 到 1000000 之间的任意数字,DynamoDB 允许扫描这一数量区间内的分段。例如,如果客户端限制可以并发运行的线程的数量,那么可以逐渐增加 TotalSegments,直到应用程序获得最佳的 Scan 性能。

监控并行扫描以便优化对预置吞吐量利用率,同时确保其他应用程序不会出现资源不足的情况。如果预置吞吐量还有剩余,但 Scan 请求中仍然遇到限制,请增加 TotalSegments 的值。如果 Scan 请求使用的预置吞吐量超过要使用的值,请减少 TotalSegments 的值。