如果我理解正确的话,你有一个主键定义如下的表:
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?
问题:我担心的是由于附加了随机数而多次查询。有没有办法组合这些查询并点击一次 dynamoDB ?
您的担忧是完全可以理解的,但是,通过BatchGetItem 获取所有记录的唯一方法是知道您打算获取的所有记录的整个主键(HASH + RANGE)。尽管乍一看最小化到服务器的 HTTP 往返似乎是最好的解决方案,但文档实际上建议完全按照您正在做的事情来避免热分区和不均匀地使用您的预置吞吐量:
为表中的项目提供统一的数据访问设计
“因为您正在随机化哈希键,所以写入表的
每天平均分布在所有哈希键值上;这
将产生更好的并行性和更高的整体吞吐量。 [...] 到
阅读给定日期的所有项目,您仍然需要查询
每个 2014-07-09.N 键(其中 N 是 1 到 200),以及您的
应用程序需要合并所有结果。然而,你会
避免让单个“热”哈希键承担所有工作负载。”
来源:http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GuidelinesForTables.html
这里还有一个有趣的点,建议在单个分区中适度使用读取...如果您从哈希键中删除随机数以便能够一次性获取所有记录,那么您很可能会陷入这个困境问题,无论您使用的是Scan、Query 还是BatchGetItem:
查询和扫描指南 - 避免读取活动的突然爆发
“请注意,Scan 使用的不仅仅是容量单位的爆发
这是一个问题。也是因为扫描很可能会消耗
它的所有容量单位都来自同一个分区,因为扫描
请求读取分区上彼此相邻的项目。这
意味着请求是命中同一个分区,导致所有
其容量单位被消耗,并限制其他请求
那个分区。如果读取数据的请求已经分散到
多个分区,则操作不会限制
特定分区。”
最后,由于您使用的是时间序列数据,因此查看文档建议的一些最佳实践可能会有所帮助:
了解时间序列数据的访问模式
为您创建的每个表指定吞吐量
要求。 DynamoDB 分配和预留资源来处理您的
具有持续低延迟的吞吐量要求。当你设计
您的应用程序和表格,您应该考虑您的应用程序的
访问模式以最有效地利用您的表
资源。
假设您设计了一个表格来跟踪您网站上的客户行为,
例如他们点击的 URL。您可以使用散列和
以客户 ID 作为散列属性的范围类型主键和
日期/时间作为范围属性。在此应用程序中,客户数据
随着时间的推移无限增长;但是,应用程序可能会显示
表中所有项目的访问模式不均匀
最新的客户数据更相关,您的应用程序可能
更频繁地访问最新项目并且随着时间的推移这些项目
访问较少,最终很少访问较旧的项目。如果
这是一种已知的访问模式,您可以考虑一下
在设计表架构时。而不是将所有项目存储在一个
单个表,您可以使用多个表来存储这些项目。为了
例如,您可以创建表来存储每月或每周的数据。为了
存储最近一个月或一周的数据的表,其中数据
访问率高,请求更高的吞吐量和表存储
旧数据,您可以降低吞吐量并节省资源。
您可以通过将“热门”项目存储在一个表中来节省资源
更高的吞吐量设置,以及另一个表中的“冷”项目
较低的吞吐量设置。您只需删除即可删除旧项目
桌子。您可以选择将这些表备份到其他存储
Amazon Simple Storage Service (Amazon S3) 等选项。删除一个
整个表比删除项目效率高得多
一个接一个,这基本上使您的写入吞吐量翻倍
删除操作与放置操作一样多。
来源:http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GuidelinesForTables.html