我有一个动态表,其中的分区键为ID
,排序键为timestamp
。我需要查询该表以基于timestamp
列查找最新的100行。当我检查query
API时,必须指定KeyConditions or KeyConditionExpression
。在这种情况下,我不想查询分区键。我怎样才能做到这一点?
scan
操作似乎不支持对结果进行排序。
我能想到的一种解决方案是在表上添加一个属性,假设status
并为此表中的每一行分配相同的值。然后在表上创建一个GSI,分区键为status
,timestamp
为排序键。然后,我可以查询分区键等于OK
的表,并根据timestamp
对结果进行排序。但是,此解决方案在规模方面效果不佳。由于表中的每一行都具有status
相同的值,因此GSI无法很好地缩放。
那么解决我的问题的最佳方法是什么?我不应该考虑使用dynamodb吗?
答案 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的全部方式,存储很便宜,计算很昂贵,优化计算并根据需要复制数据,因为无论如何它都很便宜。