DynamoDB扫描查询和BatchGet

时间:2015-04-16 12:37:36

标签: java amazon-dynamodb

我们有一个Dynamo DB表结构,其中包含Hash和Range作为主键。

Hash = date.random_number
Range = timestamp

如何获取X和Y时间戳内的项目?由于散列密钥附加了random_number,因此必须多次查询查询。是否可以提供多个哈希值和单个RangeKeyCondition。

在成本和时间方面最有效的是什么?

随机数范围从1到10.

1 个答案:

答案 0 :(得分:2)

如果我理解正确,您的表格中包含以下主键定义:

Hash Key  : date.random_number 
Range Key : timestamp

您必须记住的一件事是,无论您使用的是GetItem还是Query,您都必须能够计算应用中的Hash Key才能从表中成功检索一个或多个项目。

将随机数用作Hash Key的一部分是有意义的,这样您的记录可以均匀地分布在DynamoDB分区中,但是,您必须以您的应用程序仍可以计算这些数字的方式进行操作何时需要检索记录。

考虑到这一点,让我们创建指定需求所需的查询。您可以从表中获取多个项目的本机AWS DynamoDB操作是:

Query, BatchGetItem and Scan
  • 为了使用BatchGetItem,您需要事先知道整个主键(哈希键和范围键),但事实并非如此。

  • Scan操作会逐字查看您桌子上的每一条记录,我认为这些记录对您的要求是不必要的。

  • 最后,Query操作允许您从应用EQ(相等)运算符的表中检索一个或多个项目到Hash Key以及其他一些运算符当您没有整个Range Key或想要匹配多个时,您可以使用。

Range Key条件的运算符选项为:EQ | LE | LT | GE | GT | BEGINS_WITH | BETWEEN

在我看来,最适合您的要求的是BETWEEN运算符,如果说,让我们看看如何使用所选的SDK构建查询:

Table table = dynamoDB.getTable(tableName);

String hashKey = "<YOUR_COMPUTED_HASH_KEY>";
String timestampX = "<YOUR_TIMESTAMP_X_VALUE>";
String timestampY = "<YOUR_TIMESTAMP_Y_VALUE>";

RangeKeyCondition rangeKeyCondition = new RangeKeyCondition("RangeKeyAttributeName").between(timestampX, timestampY);

        ItemCollection<QueryOutcome> items = table.query("HashKeyAttributeName", hashKey,
            rangeKeyCondition,
            null, //FilterExpression - not used in this example
            null,  //ProjectionExpression - not used in this example
            null, //ExpressionAttributeNames - not used in this example
            null); //ExpressionAttributeValues - not used in this example

您可能需要查看以下帖子以获取有关DynamoDB主键的更多信息: DynamoDB: When to use what PK type?

问题:由于附加了random_number,我担心多次查询。有没有办法组合这些查询并命中一次dynamoDB?

您的担忧完全可以理解,但是,通过BatchGetItem获取所有记录的唯一方法是了解您打算获取的所有记录的完整主键(HASH + RANGE)。虽然最小化到服务器的HTTP往返可能看起来是最初的最佳解决方案,但文档实际上建议您正在做的事情正是为了避免热分区和不均衡地使用预配置吞吐量:

  

设计表中项目的统一数据访问

     

&#34;因为您正在随机化哈希键,所以写入表   每天均匀分布在所有哈希键值上;这个   将产生更好的并行性和更高的总吞吐量。 [...] 至   读取给定日期的所有项目,您仍然需要查询   每个2014-07-09.N键(其中N是1到200),和你的   应用程序需要合并所有结果。但是,你会的   避免单身&#34;热&#34;哈希密钥占用所有工作量。&#34;

来源:http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GuidelinesForTables.html

这里有另一个有趣的观点,表明在单个分区中适度使用读取...如果从散列键中删除随机数以便能够一次性获取所有记录,则可能会落在此问题,无论您使用的是ScanQuery还是BatchGetItem

  

查询和扫描指南 - 避免突然爆发的阅读活动

     

&#34;请注意,扫描使用的不仅仅是突发的容量单位   这是一个问题。这也是因为扫描很可能会消耗掉   因为扫描所有来自同一分区的容量单位   请求读取分区上彼此相邻的项目。这个   意味着请求正在命中同一个分区,导致所有   它的容量单位被消耗,并限制其他请求   那个分区。如果读取数据的请求已经传播开来   多个分区,那么操作就不会受到限制了   特定分区。&#34;

最后,因为您正在使用时间序列数据,所以查看文档中建议的一些最佳实践可能会有所帮助:

  

了解时间序列数据的访问模式

     

对于您创建的每个表,指定吞吐量   要求。 DynamoDB分配和预留资源来处理您的   持续低延迟的吞吐量要求。当你设计   你的应用程序和表格,你应该考虑你的应用程序   访问模式,以最有效地使用您的表格   资源。

     

假设您设计了一个表来跟踪您网站上的客户行为,   例如他们点击的网址。您可以使用哈希和设计表   范围类型主键,客户ID作为哈希属性和   日期/时间作为范围属性。在此应用程序中,客户数据   随着时间的推移无限增长;但是,应用程序可能会显示   表格中所有项目的不均匀访问模式   最新的客户数据与您的应用程序可能更相关   随着时间的推移,更频繁地访问最新的项目   访问较少,最终很少访问旧项目。如果   这是一种已知的访问模式,您可以将其考虑在内   在设计表模式时。而不是存储所有项目   单个表,您可以使用多个表来存储这些项目。对于   例如,您可以创建表来存储月度或每周数据。对于   该表存储来自最近一个月或一周的数据,其中包含数据   访问速率很高,请求更高的吞吐量和表存储   较旧的数据,您可以调低吞吐量并节省资源。

     

您可以通过存储&#34; hot&#34;来节省资源。一个表中的项目   更高的吞吐量设置,&#34;冷&#34;另一个表中的项目   较低的吞吐量设置您只需删除即可删除旧项目   表格。您可以选择将这些表备份到其他存储   Amazon Simple Storage Service(Amazon S3)等选项。正在删除   整个表比删除项目更有效   一个接一个,它基本上使您的写吞吐量翻倍   与put操作一样多的删除操作。

来源:http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GuidelinesForTables.html