Dynamodb 简明教程

DynamoDB - Scan

扫描操作会读取所有表项或二级索引。其默认功能会返回索引或表中所有项目的全部数据属性。使用 ProjectionExpression 参数对属性进行筛选。

每次扫描都会返回一个结果集,即使没有找到匹配项,也会返回一个空集。扫描检索不到 1MB 的数据,并可以选择对数据进行筛选。

Note − 扫描的参数和筛选也适用于查询。

Types of Scan Operations

Filtering − 扫描操作通过过滤器表达式提供了精细筛选功能,该表达式在扫描或查询后修改数据,在返回结果之前。表达式使用比较运算符。它们的语法与条件表达式的语法类似,但键属性除外,因为过滤器表达式不允许键属性。你不能在过滤器表达式中使用分区键或排序键。

Note − 在应用任何过滤之前,都适用于 1MB 限制。

Throughput Specifications − 扫描会消耗吞吐量,然而,消耗主要关注于项目大小,而不是返回的数据。无论你请求所有属性还是仅仅请求几个属性,消耗都保持不变。另外,使用或不使用过滤器表达式也不会影响消耗。

Pagination − DynamoDB 对结果进行分页,从而将结果分成特定页面。1MB 限制适用于返回的结果,当你超过它时,需要进行另一项扫描才能收集其余数据。 LastEvaluatedKey 值允许你执行此后续扫描。只需将该值应用到 ExclusiveStartkey 。当 LastEvaluatedKey 值变为 null 时,该操作已完成所有数据页面。不过,非 null 值并不自动表示还存在更多数据。只有 null 值才表示状态。

The Limit Parameter − 限制参数管理结果大小。DynamoDB 使用它来确定在返回数据之前处理的项目数,并且不适用于范围之外。如果你设置值为 x,DynamoDB 将返回前 x 个匹配项。

在限制参数产生部分结果的情况下,LastEvaluatedKey 值也适用。使用它来完成扫描。

Result Count − 对查询和扫描的响应还包括与 ScannedCount 和计数相关的信息,这些信息对扫描/查询的项目进行量化,并对返回的项目进行量化。如果你不进行过滤,它们的值是相同的。当你超过 1MB 时,计数仅表示已处理的部分。

Consistency − 查询结果和扫描结果最终是一致的读取结果,然而,你也可以设置强一致性读取。使用 ConsistentRead 参数更改此设置。

Note − 一致读取设置会影响消耗,因为在设为强一致性时会使用两倍的容量单位。

Performance − 查询比扫描提供更好的性能,因为扫描遍历了整个表或辅助索引,从而导致响应迟缓并大量消耗吞吐量。对于小表和过滤较少的搜索,扫描效果最佳。不过,你可以遵循一些最佳实践来设计精简扫描,例如避免突然加速读取活动并利用并行扫描。

查询根据给定条件查找某个键范围,其性能取决于它检索的数据量,而不是键的数量。操作参数和匹配项的数量会明确影响性能。

Parallel Scan

默认情况下,扫描操作顺序执行处理。然后,它们以 1MB 的部分返回数据,这会提示应用程序获取下一部分数据。对于大型表和索引,这会导致长时间扫描。

此特性还意味着扫描可能并不总是充分利用可用吞吐量。DynamoDB 将表数据分布到多个分区上,而扫描吞吐量由于它的单分区操作而仅限于一个分区。

针对此问题的一个解决方案是从逻辑上将表或索引分成段。然后,“工作程序”并行(同时)扫描段。它使用段和 TotalSegments 的参数来指定由特定工作程序扫描的段并指定处理的段的总数。

Worker Number

你必须尝试不同的工作程序值(段参数)以实现最佳应用程序性能。

Note − 拥有大量工作程序的并行扫描会影响吞吐量,可能消耗所有吞吐量。通过限制参数管理此问题,你可以使用该参数阻止单个工作程序消耗所有吞吐量。

以下是深度扫描的示例。

Note − 以下程序可能会假设有一个已创建的数据源。在尝试执行之前,获得支持库并创建必要的数据源(具备所需特征的表格或其他引用的源)。

此示例还使用了 Eclipse IDE、AWS 凭据文件和 Eclipse AWS Java 项目中的 AWS Toolkit。

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient;
import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.Item;
import com.amazonaws.services.dynamodbv2.document.ItemCollection;
import com.amazonaws.services.dynamodbv2.document.ScanOutcome;
import com.amazonaws.services.dynamodbv2.document.Table;

public class ScanOpSample {
   static DynamoDB dynamoDB = new DynamoDB(
      new AmazonDynamoDBClient(new ProfileCredentialsProvider()));
   static String tableName = "ProductList";

   public static void main(String[] args) throws Exception {
      findProductsUnderOneHun();                       //finds products under 100 dollars
   }
   private static void findProductsUnderOneHun() {
      Table table = dynamoDB.getTable(tableName);
      Map<String, Object> expressionAttributeValues = new HashMap<String, Object>();
      expressionAttributeValues.put(":pr", 100);

      ItemCollection<ScanOutcome> items = table.scan (
         "Price < :pr",                                  //FilterExpression
         "ID, Nomenclature, ProductCategory, Price",     //ProjectionExpression
         null,                                           //No ExpressionAttributeNames
         expressionAttributeValues);

      System.out.println("Scanned " + tableName + " to find items under $100.");
      Iterator<Item> iterator = items.iterator();

      while (iterator.hasNext()) {
         System.out.println(iterator.next().toJSONPretty());
      }
   }
}