Amazon DynamoDB
开发人员指南 (API Version 2012-08-10)
AWS 服务或AWS文档中描述的功能,可能因地区/位置而异。点 击 Getting Started with Amazon AWS to see specific differences applicable to the China (Beijing) Region.

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

本节介绍 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 操作引起的容量单位使用量陡增所带来的影响,以及这种情况对同一表的其他请求所造成的影响。

 

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

  • 降低页面大小

    由于扫描操作会读取整个页面(默认情况下为 1 MB),因此,您可以通过设置较小的页面大小来降低扫描操作的影响。您可以使用 Scan 操作提供的 Limit 参数设置请求的页面大小。设置了较小的页面大小后,每个 QueryScan 请求都会使用更少的读取操作,并会在每个请求之间“停顿”。例如,如果每个项目的大小为 4 KB,并且您将页面大小设置为 40 个项目,那么 Query 请求将只占用 40 次强一致性读取操作或 20 次最终一致性读取操作。如果占用较小容量单位的 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 的值。