我希望存储用户事件的日志。这将是很多条目,所以我认为DynamoDB会很好,因为其他一切都在那里托管。
我需要以两种方式查询这些事件,即用户日期(范围)的事件总数,以及偶尔日期的所有事件。
我打算将其作为user id
(密钥),sequence number
(密钥),date
,time
和duration
存储在一个表中。< / p>
它应该是多个表吗?如何最有效地完成这项工作?
答案 0 :(得分:0)
对于少量数据,这种结构是可以的。 请记住,序列号(您的范围键)必须由您提供。选择日期作为unix时间戳,以毫秒精度作为排序键似乎是个好主意。
不需要额外的表格。 但是,您的结构在很大程度上取决于您想要实现的读写容量和数据大小。
假设您的user_id是您的分区键。
对于每个不同的分区键值,所有表和索引项的总大小不能超过10 GB。 单个分区最多可支持3,000个读取容量单位或1,000个写入容量单位。
您需要考虑这些限制来创建分区键。 例如,非常活跃的用户有许多事件,因此您需要超过1000个写入容量单位。不幸的是,您已选择用户ID作为分区。
在这种情况下,您只能使用1000个写入容量单位,因此可能会出现故障。
您需要拥有不同的结构。例如,分区名称就像 user_id_1 user_id_2等因此,分区命名机制根据应用程序的需要将数据传播到分区。
检查关于dynamodb限制的这些链接。
答案 1 :(得分:0)
我建议你的事件表采用以下结构:
将事件时间戳作为范围键应该足以为事件提供唯一性(除非用户可以在同一毫秒内拥有多个事件),因此您不需要序列号。
拥有这样的架构,您可以使用简单的query为用户获取日期的所有事件。
不幸的是,DynamoDB不支持聚合查询,因此您无法快速获得用户的总事件数(您必须查询所有记录并手动计算总数)。 因此,我建议为用户事件统计信息创建单独的表,如下所示:
因此,在事件表中添加新记录后,您必须在统计信息表中为用户增加事件计数器,如下所示:
var dynamodbDoc = new AWS.DynamoDB.DocumentClient();
var params = {
TableName : "user_events_stats",
Key: {
userId: "65716110-f4df-11e6-bc64-92361f002671" ,
date: "2017-02-17",
},
UpdateExpression: "SET #events_cnt = if_not_exists(#events_cnt, :zero) + :one",
ExpressionAttributeNames: {
"#events_cnt": "events_cnt",
},
ExpressionAttributeValues: {
":one": 1,
":zero": 0,
},
};
dynamodbDoc.update(params, function(err, data) {
});