我是从一个关系型数据库背景的,并试图与亚马逊DynamoDB工作
我有一个哈希键“数据ID”和一系列“CreatedAt”和一帮在这一个项目表。
我试图得到一个特定的日期后创建和按日期排序的所有项目。 这是一个关系型数据库非常简单。
在DynamoDB我能找到的最接近的是一个查询和使用范围比重点更大的过滤器。 唯一的问题是,执行查询,我需要它违背了目的哈希键。
所以我在做什么错? 是我的表架构错了,不应该散列键是唯一的? 或有另一种方式来查询?
我是从一个关系型数据库背景的,并试图与亚马逊DynamoDB工作
我有一个哈希键“数据ID”和一系列“CreatedAt”和一帮在这一个项目表。
我试图得到一个特定的日期后创建和按日期排序的所有项目。 这是一个关系型数据库非常简单。
在DynamoDB我能找到的最接近的是一个查询和使用范围比重点更大的过滤器。 唯一的问题是,执行查询,我需要它违背了目的哈希键。
所以我在做什么错? 是我的表架构错了,不应该散列键是唯一的? 或有另一种方式来查询?
更新答案:
DynamoDB允许二级索引的规范在这种查询的帮助。 辅助索引可以是全球性的,这意味着指数地跨哈希键,或者该指数将每个哈希键分区中存在,因此需要散列键本地含义整个表也被指定做查询时。
对于用例在这个问题上,你会想对“CreatedAt”字段中使用全局二级索引。
欲了解更多有关DynamoDB二级指标看二级索引文件
原来的答案:
DynamoDB不允许只在范围键索引的查找。 散列键是必需的,以便服务知道看哪个分区中查找数据。
当然,你可以执行扫描操作的日期值过滤,然而这将需要全表扫描,所以它是不理想的。
如果您需要通过在多个主键的时间进行记录编索引的查找,DynamoDB可能不是理想的服务供您使用,或者您可能需要使用一个单独的表(在DynamoDB或关系存储)存储项目您可以执行对编索引的查找元数据。
鉴于当前的表结构,这是目前不可能在DynamoDB。 巨大的挑战是要了解该表(分区)的哈希键应该创建单独的表来处理。 在某些方面,这是真正强大的(考虑分区键的为每一个用户或客户,等...创建新表)。
查询只能在一个分区来完成。 这是真正的故事的结尾。 这意味着如果你想按日期查询(你要使用毫秒纪元以来的),那么所有你想在一个单一的查询检索必须具有相同的散列(分区键)的项目。
我应该有资格这一点。 你绝对可以scan
通过你所寻找的,这是没有问题的标准,但是这意味着你将在你的表中寻找每一个单排,然后检查是否该行拥有符合您参数的日期。 这实在是昂贵,特别是如果你在存储日期事件摆在首位的企业(即你有很多行。)
你可能很想把所有的数据在一个分区来解决这个问题,你绝对可以,但是你的吞吐量将痛苦地低,因为每个分区只接收总集额的一小部分。
做的最好的事情是确定更有效的分区创建保存数据:
你真的需要看看所有的行,或者是它只是行由特定用户?
难道没事先缩小按月名单,并做多个查询(每月一)? 或一年?
如果你正在做的时间序列分析有几个选项,更改分区键的东西computated上PUT
,使query
变得更容易,或者使用其他AWS产品如室壁运动这使其追加,只记录。
你的哈希键(排序的主)必须是唯一的(除非你有一个系列,如由他人说明)。
你的情况,查询您的表,你应该有一个辅助指标。
| ID | DataID | Created | Data |
|------+--------+---------+------|
| hash | xxxxx | 1234567 | blah |
你的散列键ID您的辅助指数定义为:数据ID创建的索引(这是DynamoDB将使用的名称)
然后,你可以做这样的查询:
var params = {
TableName: "Table",
IndexName: "DataID-Created-index",
KeyConditionExpression: "DataID = :v_ID AND Created > :v_created",
ExpressionAttributeValues: {":v_ID": {S: "some_id"},
":v_created": {N: "timestamp"}
},
ProjectionExpression: "ID, DataID, Created, Data"
};
ddb.query(params, function(err, data) {
if (err)
console.log(err);
else {
data.Items.sort(function(a, b) {
return parseFloat(a.Created.N) - parseFloat(b.Created.N);
});
// More code here
}
});
基本上你的查询是这样的:
SELECT * FROM TABLE WHERE DataID = "some_id" AND Created > timestamp;
二级索引将增加所需的读/写容量的单位,所以你需要考虑这一点。 它仍然比做一个扫描,这将是昂贵的读取和时间(和被限制在100个项目,我相信)好了很多。
这可能不是做的最好的方式,但对于使用RD(我也用于SQL),这是获得高效的最快方法的人。 由于在关于模式没有任何限制,你可以掀起一些作品,一旦你有带宽上最有效的工作方式,你可以改变周围的事物。
办法我跟着来解决这个问题是创建一个全球次级指数如下。 不知道这是最好的办法,但希望如果它是有用的人。
Hash Key | Range Key
------------------------------------
Date value of CreatedAt | CreatedAt
限制强加在HTTP API用户指定的天数来获取数据,默认为24小时。
这样一来,我可以随时指定HashKey作为当前日期的一天,RangeKey可以使用>和<运营商在检索。 这样的数据也分布在多个碎片。
你可以做沿着“产品类别” ID的行哈希键的东西,那么范围键与附加在末尾的唯一ID时间戳的组合。 这样,你知道的哈希键,仍然可以查询日期大于。
你可以有多个相同的哈希键; 但只有当你有一个变化的范围键。 认为它喜欢的文件格式; 只要他们的格式是不同的,你可以在同一个文件夹中两个文件具有相同的名称。 如果它们的格式是一样的,他们的名字必须是不同的。 同样的概念也适用于DynamoDB的hash /量程键; 只是觉得散列的名称和范围内的格式。
此外,如果他们有这些在OP的时候,我不记得(我不相信他们所做的那样),但他们现在提供本地二级指标。
我的这些理解是,它现在应该让你不必做一个全面的扫描执行所需的查询。 缺点是,这些指标必须在创建表中指定,也(我相信)创建一个项目时不能为空。 此外,他们还需要更多的吞吐量(虽然一般不如扫描)和存储,所以它不是一个完美的解决方案,而是一个可行的选择,对于一些。
我还是建议迈克·布兰特的答案使用DynamoDB,虽然首选方法; 并使用该方法喽。 就我而言,我只是有一个中央台只有一个散列键作为我的ID,然后有一个哈希和范围可以查询的辅助表,然后将项目指向的代码到中央台的“利益项目”,直接。
可以亚马逊DynamoDB文档中找到关于二级指标的附加数据在这里为那些有兴趣。
不管怎么说,希望这将帮助其他人在这个线程出现这种情况。
更新答案还有就是要做到这一点使用迪纳摩的数据库查询与预测的吞吐量没有便捷的途径。 一个(次优)的选择是使用一个GSI用人工HashKey&CreatedAt。 然后通过HashKey单独查询和提ScanIndexForward命令的结果。 如果你能拿出一个自然HashKey(说项目等类别),那么这个方法是一个胜利者。 在另一方面,如果你把所有项目一样HashKey,那么这将主要影响吞吐量时,当你的数据集增长超过10GB(一个分区)
原来的答案:您可以通过使用GSI在DynamoDB现在做到这一点。 使“CreatedAt”字段作为GSI并发出像(GT some_date)查询。 存储日期为数字(毫秒纪元以来的)这种类型的查询。
详情请访问:全球辅助索引-亚马逊DynamoDB: http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GSI.html#GSI.Using
这是一个非常强大的功能。 请注意,查询仅限于(EQ | LE | LT | GE | GT | BEGINS_WITH | BETWEEN)条件-亚马逊DynamoDB: http://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Condition.html