我们正在考虑将DynamoDB用于预期的大型数据集。我来自强大的SQL背景,因此No-SQL思维方式对我来说是新的。
我遇到了问题和设计,但遇到了似乎死路一条的问题 文档说明要确保你的Hash密钥被广泛分发以帮助提高性能,这是有道理的。
我将为用户录制各种数据点/动作。我觉得散列键应该是user-id,而我的range键可以是执行的动作。
现在,如果我想要用户#1执行的所有操作,我可以轻松查询 但是,如果我想要所有执行操作X的USERS,我不能在没有表扫描的情况下这样做。来自Query documentation:
Query操作使用表主键直接访问表中的项,或使用索引键从索引访问。 您必须提供特定的哈希键值。
所以看起来我似乎只能从特定用户那里获取数据,除非我愿意做一个table scan,这个速度较慢并消耗很多容量单位。
我认为,我的问题最终是一个设计问题。也许我在No-SQL方面缺少一些东西?我的哈希键应该是别的吗?或者仅仅是我的要求不适合No-SQL(更具体地说,DynamoDB)?
几乎就好像哈希键是一种使用DynamoDB的分组。我考虑将哈希键更改为我们打算实施的操作,但后来我没有广泛分发我的密钥......
答案 0 :(得分:2)
DynamoDb满足您允许两种类型查询的要求的方法是将数据存储在两个表中,一个表使用散列键user-id和range key action-id,另一个表使用散列键action-id和range key用户ID。
您应该考虑是否需要两个表中的所有数据,或者是否可以是汇总表。例如,假设您的可能操作数量有限。您可能想要一个每个用户只有一行的表,而不是将每个操作的完整记录放在用户键控表中:用户ID的哈希键,以及第二列的多值,并且是一个列表用户至少执行过一次的action-id。
答案 1 :(得分:1)
我猜global secondary indexes选项更好,因为你得到一张表。
创建两个表将创建冗余和其他工作,以便在任何一个表上执行任何CUD(创建,更新,删除)操作时保持一致性。
答案 2 :(得分:1)
您必须创建Global Secondary Index(GSI)。这样做是因为它创建了第二对散列和范围键,它们与原始键不同。然后,您可以通过在参数中包含索引名称来查询同一个表。
JS中的示例:
var table = tablename;
var index = actionId-username-gsi;
var action = actionId;
var params = {
TableName : table,
IndexName : index,
KeyConditionExpression : 'actionId = :v_actionId',
ExpressionAttributeValues : {
':v_actionId': { N : action }
},
ProjectionExpression : 'actionId, username'
};
ddb.query(params, err) {
if(err) {
// Oh well
} else {
// Do something
}
};
这将查询 actionId-username-gsi 索引并查找具有所提供值的任何actionId哈希值。使用ProjectionExpression将仅返回指定的属性'每个项目的价值,如果成为一个问题,降低吞吐量。我希望这有助于回答你的问题。