app*_*ief 86 amazon-web-services nosql amazon-dynamodb
我来自关系数据库背景,并尝试使用亚马逊的DynamoDB
我有一个表,其中包含一个哈希键"DataID"和一个范围"CreatedAt"以及一系列项目.
我正在尝试获取在特定日期之后创建的所有项目并按日期排序.这在关系数据库中非常简单.
在DynamoDB中,我能找到的最接近的是查询并使用大于filter的范围键.唯一的问题是,为了执行查询,我需要一个破坏目的的哈希键.
那么我做错了什么?我的表架构是错误的,哈希键不应该是唯一的吗?还是有另一种查询方式?
War*_*rad 37
鉴于您当前的表结构,目前在DynamoDB中无法实现.最大的挑战是要理解表(分区)的哈希键应该被视为创建单独的表.在某些方面,这非常强大(将分区键视为为每个用户或客户创建新表等等).
查询只能在单个分区中完成.这真的是故事的结局.这意味着如果您想按日期查询(您希望从epoch开始使用msec),那么您要在单个查询中检索的所有项目必须具有相同的哈希(分区键).
我应该有资格这个.您绝对可以scan按照您要查找的标准,这没问题,但这意味着您将查看表中的每一行,然后检查该行是否具有与您的参数匹配的日期.这真的很贵,特别是如果你是在第一时间按日期存储事件(即你有很多行).
您可能想要将所有数据放在一个分区中来解决问题,但绝对可以,但是由于每个分区只接收总设置量的一小部分,因此吞吐量会非常低.
最好的办法是确定要创建的更有用的分区来保存数据:
你真的需要查看所有行,还是只有特定用户的行?
是否可以按月缩小列表范围,并进行多次查询(每月一次)?还是按年?
如果您正在进行时间序列分析,则有几个选项,将分区键更改为计算的内容PUT以使其query更容易,或者使用另一个像kinesis这样的aws产品,这些产品适合仅附加日志记录.
Mik*_*ant 33
更新答案:
DynamoDB允许指定二级索引以帮助进行此类查询.辅助索引可以是全局的,也就是说索引跨越散列键跨越整个表,或者本地意味着索引将存在于每个散列键分区中,因此在进行查询时也需要指定散列键.
对于此问题中的用例,您可能希望在"CreatedAt"字段上使用全局二级索引.
有关DynamoDB二级索引的更多信息,请参阅二级索引文档
原答案:
DynamoDB不允许仅对范围键进行索引查找.需要散列密钥,以便服务知道要查找哪个分区以查找数据.
您当然可以执行扫描操作以按日期值进行过滤,但这需要全表扫描,因此它并不理想.
如果需要跨多个主键按时间执行索引的索引查找,DynamoDB可能不是您使用的理想服务,或者您可能需要使用单独的表(在DynamoDB或关系存储中)来存储项目您可以执行索引查找的元数据.
解决这个问题的方法是通过创建全局二级索引,如下所示.不确定这是否是最好的方法,但希望如果它对某人有用.
Hash Key | Range Key
------------------------------------
Date value of CreatedAt | CreatedAt
Run Code Online (Sandbox Code Playgroud)
对HTTP API用户施加的限制,以指定检索数据的天数,默认为24小时.
这样,我总是可以将HashKey指定为当前日期,RangeKey可以在检索时使用>和<运算符.这样,数据也分布在多个分片上.
您的哈希键(排序主键)必须是唯一的(除非您有其他人声明的范围).
在您的情况下,要查询您的表,您应该有一个二级索引.
| ID | DataID | Created | Data |
|------+--------+---------+------|
| hash | xxxxx | 1234567 | blah |
Run Code Online (Sandbox Code Playgroud)
您的哈希密钥是ID您的二级索引定义为:DataID-Created-index(这是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
}
});
Run Code Online (Sandbox Code Playgroud)
基本上你的查询看起来像:
SELECT * FROM TABLE WHERE DataID = "some_id" AND Created > timestamp;
Run Code Online (Sandbox Code Playgroud)
二级索引将增加所需的读/写容量单位,因此您需要考虑这一点.它仍然比扫描好很多,这在读取和时间上都是昂贵的(并且我认为限于100个项目).
这可能不是最好的方法,但对于习惯于RD的人(我也习惯于SQL)来说,这是提高工作效率的最快方法.由于没有关于模式的限制,你可以掀起一些有效的东西,一旦你有了最有效的工作带宽,就可以改变一切.
| 归档时间: |
|
| 查看次数: |
83440 次 |
| 最近记录: |