单个分区键值是否有 10GB 的 DynamoDB 最大分区大小?

Is there a DynamoDB max partition size of 10GB for a single partition key value?

我已经阅读了很多关于设计分区键和排序键的 DynamoDB 文档,但我认为我一定遗漏了一些基本的东西。

如果您的分区键设计不当,当单个分区键值的数据超过 10GB 时会发生什么情况?

'Understand Partition Behaviour' 部分指出:

"A single partition can hold approximately 10 GB of data"

如何对单个分区键进行分区?

http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GuidelinesForTables.html#GuidelinesForTables.Partitions

文档还讨论了本地二级索引限制为 10GB 数据的限制,之后您会开始收到错误。

"The maximum size of any item collection is 10 GB. This limit does not apply to tables without local secondary indexes; only tables that have one or more local secondary indexes are affected."

http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LSI.html#LSI.ItemCollections

这个我能理解。如果单个分区键超过 10GB,它是否还有其他魔力可以对数据进行分区。还是它只是不断增长那个分区?这对您的按键设计有何影响?

这个问题的背景是我见过很多在多租户环境中使用 TenantId 之类的东西作为分区键的例子。但是,如果特定 TenantId 可以拥有超过 10 GB 的数据,这似乎是有限的。

我一定是漏了什么?

TL;DR - 通过在分区函数中包含范围键值,即使它们具有相同的分区键值也可以拆分。


长版:

这是一个很好的问题,在文档 here and here. As the documentation states, items in a DynamoDB table are partitioned based on their partition key value (which used to be called hash key) into one or multiple partitions, using a hashing function 中得到了解决。分区数是根据所需的最大总吞吐量以及键 space 中项目的分布得出的。换句话说,如果选择分区键,使其在分区键 space 上均匀分布项目,则最终每个分区具有大致相同数量的项目。每个分区中的项目数大约等于 table 中的项目总数除以分区数。

文档还指出每个分区被限制为大约 10GB space。一旦存储在任何分区中的所有项目的大小总和超过 10GB,DynamoDB 将启动一个后台进程,自动透明地将这些分区一分为二——从而产生两个新分区。再一次,如果项目均匀分布,这很好,因为每个新的子分区最终将包含原始分区中大约一半的项目。

拆分的一个重要方面是每个拆分分区的吞吐量都是原始分区可用吞吐量的一半。

到目前为止,我们已经介绍了快乐的案例。

另一方面,可能有一个或几个分区键值对应于大量项目。如果 table 架构使用排序键并且多个项目散列到同一分区键,则通常会发生这种情况。在这种情况下,单个分区键可能负责总共占用超过 10 GB 的项目。这将导致分裂。在这种情况下,DynamoDB 仍会创建两个新分区,但它不会仅使用分区键来决定将项目存储在哪个子分区中,它还会使用排序键。

例子

不失一般性并使事情更容易推理,假设有一个 table,其中分区键是字母 (A-Z),数字用作排序键。

假设table大约有9个分区,那么字母A,B,C会存放在分区1,字母D,E,F会存放在分区2,以此类推

在下图中,分区边界被标记为 h(A0)h(D0) 等以表明,例如,存储在第一个分区中的项目是分区键散列到的项目h(A0)h(D0) 之间的值 - 0 是有意的,接下来会派上用场。

[ h(A0) ]--------[ h(D0) ]---------[ h(G0) ]-------[ h(J0) ]-------[ h(M0) ]- ..
  |   A    B    C   |       E    F   |   G      I    |   J    K   L  |
  |   1    1    1   |       1    1   |   1      1    |   1    1   1  |
  |   2    2    2   |       2    2   |          2    |        2      |
  |   3         3   |            3   |          3    |               |
  ..                ..               ..              ..              ..
  |            100  |           500  |               |               |
  +-----------------+----------------+---------------+---------------+-- ..

请注意,对于大多数分区键值,table 中有 1 到 3 个项目,但有两个分区键值:DF 不是看起来太好了。 D 有 100 个项目,而 F 有 500 个项目。

如果不断添加分区键值为 F 的项目,最终分区 [h(D0)-h(G0)) 将拆分。为了能够拆分具有相同哈希键的项目,必须使用范围键值,因此我们最终会遇到以下情况:

..[ h(D0) ]------------/ [ h(F500) ] / ----------[ h(G0) ]- ..
      |       E       F       |           F         |
      |       1       1       |          501        |
      |       2       2       |          502        |
      |               3       |          503        |
      ..                      ..                    ..
      |              500      |         1000        |
.. ---+-----------------------+---------------------+--- ..

原分区[h(D0)-h(G0))被拆分为[h(D0)-h(F500))[h(F500)-h(G0))

我希望这有助于可视化项目通常基于通过将散列函数应用于其分区键值而获得的散列值映射到分区,但如果需要,被散列的值可以包括分区键 +排序键值也是如此。