如何查询按“时间戳”排序的dynamodb表?

时间:2020-05-18 06:55:05

标签: amazon-web-services amazon-dynamodb

我有一个动态表,其中的分区键为ID,排序键为timestamp。我需要查询该表以基于timestamp列查找最新的100行。当我检查query API时,必须指定KeyConditions or KeyConditionExpression。在这种情况下,我不想查询分区键。我怎样才能做到这一点?

scan操作似乎不支持对结果进行排序。

我能想到的一种解决方案是在表上添加一个属性,假设status并为此表中的每一行分配相同的值。然后在表上创建一个GSI,分区键为statustimestamp为排序键。然后,我可以查询分区键等于OK的表,并根据timestamp对结果进行排序。但是,此解决方案在规模方面效果不佳。由于表中的每一行都具有status相同的值,因此GSI无法很好地缩放。

那么解决我的问题的最佳方法是什么?我不应该考虑使用dynamodb吗?

2 个答案:

答案 0 :(得分:2)

您的方法有效。而且,如果您将GSI分区键中的哑元值保持较小(即1个字节),则不会对性能产生太大影响。关于具有相同分区键的所有项目的伸缩问题,如果集合大小增长到大于10 GB,则DynamoDB splits partitions by sort key

还请查看与您的this StackOverflow question类似的内容。

答案 1 :(得分:1)

排序的元素在分区内排序。您需要将所有结果都放在同一分区上。

但是很明显,您不希望只有一个分区,而是返回到SQL数据库。在DynamoDB中完成此操作的不舒服且不轻松的方法是使用Streams。当您有新元素或更新时,可以检查这些元素是否在顶部N位置。例如,如果他们要替换该值,则说您有钱的人:

PK            Attributes:  
#Entity#21    name=Fred.      money=5,000     
#Entity#22    name=Bob.       money=10,000     
#Entity#23    name=Smith.     money=1,000     
...

然后,我们可以跟踪前10名最富有的人:

PK              SORT               Attributes:      
#Money#Highest    1               id=#Entity#22    value=10,000
#Money#Highest    2               id=#Entity#102   value=9,000
...

然后,当您想要最富有的人时,可以使用PK=#Money#Highest进行查询。您还可以根据查询复制更多属性。这几乎是一成不变的,如果您想计算跨分区的最高something,则可以设置流并自己完成。请注意,尽管这些总数会过时几秒钟,具体取决于您的流设置。您串流Lambda就像是这样:

const handler = (event, context, callback) => {
    event.Records.forEach((ev, i) => {
        if (ev.eventName === "INSERT" || ev.eventName === "UPDATE" || ) {
          // TODO
        }
      }
    }

我知道这很烦人!但这是实现这些东西的怪异方法。但这非常快速,因为您只需要检索预先计算的值。这就是您使用Dynamo的全部方式,存储很便宜,计算很昂贵,优化计算并根据需要复制数据,因为无论如何它都很便宜。