【问题标题】:DynamoDB Scan Query and BatchGetDynamoDB 扫描查询和 BatchGet
【发布时间】:2015-04-16 12:37:36
【问题描述】:

我们有一个由 Hash 和 Range 作为主键的 Dynamo DB 表结构。

Hash = date.random_number
Range = timestamp

如何获取 X 和 Y 时间戳内的项目?由于散列键附加了随机数,因此必须触发多次查询。是否可以给出多个哈希值和单个 RangeKeyCondition。

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

随机数范围是从 1 到 10。

【问题讨论】:

  • 你的问题不太清楚。 “以及,为什么我可以从 X 时间戳到 Y 时间戳获取项目”是什么意思。
  • 猜测是 OP 想说的。看起来不知道如何获取当前时间 - x 分钟或如何将两个时间瞬间放在查询之间。
  • 1.为什么在日期之后需要随机数?你有一个带有日期和时间的时间戳吗?您尝试过哪些查询?你知道如何获取当前时间 - 10 分钟吗?

标签: java amazon-dynamodb


【解决方案1】:

如果我理解正确的话,你有一个主键定义如下的表:

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

这里还有一个有趣的点,建议在单个分区中适度使用读取...如果您从哈希键中删除随机数以便能够一次性获取所有记录,那么您很可能会陷入这个困境问题,无论您使用的是ScanQuery 还是BatchGetItem

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

“请注意,Scan 使用的不仅仅是容量单位的爆发 这是一个问题。也是因为扫描很可能会消耗 它的所有容量单位都来自同一个分区,因为扫描 请求读取分区上彼此相邻的项目。这 意味着请求是命中同一个分区,导致所有 其容量单位被消耗,并限制其他请求 那个分区。如果读取数据的请求已经分散到 多个分区,则操作不会限制 特定分区。”

最后,由于您使用的是时间序列数据,因此查看文档建议的一些最佳实践可能会有所帮助:

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

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

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

您可以通过将“热门”项目存储在一个表中来节省资源 更高的吞吐量设置,以及另一个表中的“冷”项目 较低的吞吐量设置。您只需删除即可删除旧项目 桌子。您可以选择将这些表备份到其他存储 Amazon Simple Storage Service (Amazon S3) 等选项。删除一个 整个表比删除项目效率高得多 一个接一个,这基本上使您的写入吞吐量翻倍 删除操作与放置操作一样多。

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

【讨论】:

  • spin,是的,你没看错。由于哈希键附加了一个随机数,如果随机数在 1 到 10 之间,我们将查询 10 次。
  • 字符串 timestampX = "2015-04-20_07:37:30.366";字符串时间戳Y = "2015-04-20_07:37:33.366"; RangeKeyCondition rangeKeyCondition = new RangeKeyCondition("timestamp").between(timestampX, timestampY);诠释 i = 0; while (i items = table.query("day", hashKey, rangeKeyCondition);迭代器 迭代器 = items.iterator(); while (iterator.hasNext()) { System.out.println(iterator.next().toJSONPretty()); } 我++; }
  • 很抱歉没有正确使用 StackOverflow...我担心的是由于附加了随机数而多次查询。有没有办法组合这些查询并点击一次 dynamoDB ?
  • 您好,Javalkar 先生,我已经更新了我的答案以包含您的最后一个问题,如果您认为这是正确的答案,请单击它旁边的复选标记,以便正确引导其他用户.我希望这会有所帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-19
相关资源
最近更新 更多