首页 > 解决方案 > 如何在 aws-dynamodb 中通过 DateTimeStamp desc limit 10 实现`select * from InternalProductionDb order

问题描述

我在dynamodb中有一张表,表结构如下: 内部生产数据库 PKStatusIdString,排序键DateTimeStampNumber。我想达到select * from InternalProductionDb order by DateTimeStamp desc limit 10;

let params = {
    ExpressionAttributeValues: {
        ':min': {
            N: '200000000000'
        },
        ':max': {
            N: '300000000000'
        },
        ':beg':{
            S:'2'
        }
    },
    TableName: "InternalProductionDb",
    ConsistentRead: true,
    Limit: 10,
    KeyConditionExpression:' DateTimeStamp between :min and :max and begins_with(StatusId,:beg)' ,
    ScanIndexForward:true
};
let res = await ddb.query(params).promise();
console.dir(res);
return res;

其实因为不需要做任何条件判断,其实也不需要KeyConditionExpression,但是API一定要指定KeyConditionExpression参数。所以写了两个必然的判断语句。我认为这太复杂了,我得到了一个错误。错误是Query key condition not supported,那么有人知道正确的解决方案吗?非常感谢

标签: amazon-dynamodb

解决方案


DynamoDB 不是关系数据库!您要求的是针对您的架构的非常复杂的查询。

您需要针对时间序列查询优化的架构,例如“获取表中的 10 个最新项目”。这样的模式必须在水平缩放(这是 Dynamo 开箱即用的)和数据的局部性之间提供折衷,以便组合您的响应。

一种选择是按日期对数据进行分区。例如,将日期用作分区键,将时间戳用作排序键。然后,假设您获得了足够的数据,为了回答您的查询,您只需要在今天和可能的前一天查看。

如果您每天不能总是获得足够的数据,事情当然会变得更棘手,在这种情况下,找出最近的日期会更加复杂。您可以将分区键的粒度更改为按周/月。

您还可以使用其他某种模式,将“最近”数据全部保存在一个分区中,并将旧数据轮换出去。

但这里有另一个想法:您可以创建两个表 - 一个存储每个项目,一个只保留最新的。您可以在“最近的表”上使用 TTL 并删除早于某个阈值的记录,并且在此表上您可以设置架构以使所有项目都位于同一分区中(即它们具有相同的 PK 值)和然后使用时间戳作为排序键。然后获得最近的前 10 名就变成了一个简单的查询。

或者,您可以将关系数据库与 DynamoDB 结合使用进行分析查询。

进一步阅读:DynamoDB 上时间序列数据库的最佳实践


推荐阅读