【问题标题】:Why shouldn't I give all my DynamoDB items in the same partition key value?为什么我不应该将我的所有 DynamoDB 项目赋予相同的分区键值?
【发布时间】:2020-11-21 12:24:48
【问题描述】:
有plentyofresources建议使用高基数属性作为分区键。我的问题是,如果我改为完全相反并为我的所有项目提供相同分区键值会发生什么(区分仅通过排序键),允许我查询整个表?
这会导致性能和/或热分区问题吗?如果热分区没有达到3000 RCUs/1000 WCUs,它们是否对自适应容量也有影响?即使这样,如果查询在我的排序键中均匀分布怎么办?
共识似乎是我们不应该这样做,但我的问题是:为什么不呢?
【问题讨论】:
标签:
amazon-web-services
amazon-dynamodb
primary-key
partitioning
【解决方案1】:
建议和最佳实践可指导您从使用 DynamoDB 中获得最大收益。通常,人们使用 DynamoDB 来存储在传统 RDBMS 中存在可扩展性问题的海量和高速数据。
如果您谈论的是聚合访问速度不超过 3000 个 RCU/1000 个 WCU 的少量数据,那么这还不足以解决您使用 DynamoDB 的痛点。事实上,如果您使用传统的 RDBMS,您可能可以获得相同水平的性能。但是,一旦您的应用程序变得流行,或者即使您的应用程序在 5 分钟的时间跨度内刚刚遇到峰值,数据量和速度都会迅速增加,您会感到痛苦。这就是为什么遵循最佳实践通常会给您这种未来证明的好处。
即使这样,如果查询在我的排序键中均匀分布怎么办?
如果集合大小超过 10 GB,DynamoDB 会按排序键拆分分区。 [ref] 所以很可能你还是会遇到热分区问题。
不要误会我的意思。有些用例需要使用相同的分区键,例如建模数据的一对多和多对多关系。这些都是有效的用例,因为数据本质上是关系型的,这是在 DynamoDB 中对其进行有效建模的唯一方法。但是,如果您选择执行与文档建议完全相反的操作,那么您的可扩展性将受到限制,您将无法从 DynamoDB 中获得全部好处。
【解决方案2】:
好的,我们开始吧,我会用一个示例应用来做。
假设您正在为加拿大创建人口普查申请。您的分区键将是省或地区名称,其中一共有 13 个 iirc。您加载初始数据,一切都很好。你打开它让用户进来。一切都很好,但是当每个人都在家并且刚刚收到一张卡片说他们应该去你的网站时。那么,加拿大的人口中心在哪里?安大略省和魁北克省拥有最多,它们恰好位于同一个表分区中。哎呀。是的,适应能力会试图拯救你,但在短期内,现在有成千上万的人(或更多)试图使用你的网站。该分区现在很热门,因为它达到了每个分区配额 3000 IOPS,只有多伦多的一个部分在线。 DynamoDB 已经在尝试将项目移动到其他分区并创建更多项目以使您免于犯错,但您的用户已经受到限制。你选的不好。 Twitter/reddit/etc 现在正在爆发令人讨厌的 cmets,我不会在这里引用。与此同时,爱德华王子岛和育空地区的分区并没有起到多大作用。如果您选择了不同的分区键或使用带有省/地区名称的写入分片,则项目会更均匀地分布,这不会有问题。
也就是说,在另一种情况下,使用少量应用程序和低基数 PK,一切可能都很好。随着该应用程序的扩展,您的错误将变得明显。如果它永远不会扩展,那么它可能会很好......为什么要麻烦呢?
希望你明白这一点。此外,这种事情并不是 DynamoDB 独有的。我曾与许多其他数据库合作过,这些数据库在可能成为问题的地方进行分区。至少 DynamoDB 足够聪明,可以随着时间的推移尝试将您从错误中拯救出来,但为什么要让自己面对问题呢?
【解决方案3】:
对于可扩展的应用程序,您不能假设它的 IOPS 永远不会受到影响。而且由于每个区域的流量从来都不是均匀的,一些数据中心的流量可能比另一个数据中心高得多。并且在某些特殊事件期间,预计会出现巨大的流量峰值(例如,Alexa 设备在圣诞节访问),自适应能力在这种情况下会以不确定的延迟生效——因此您需要提前计划扩大规模,并且当然一开始就尽量避免潜在的热分区问题。