TL;DR - 通过将范围键值包含到分区函数中,即使它们具有相同的分区键值,也可以拆分项目。
长版:
这是一个很好的问题,在此处和此处的文档中都有说明。如文档所述,DynamoDB 表中的项目使用 ah ashing 函数根据其分区键值(以前称为hash key)划分为一个或多个分区. 分区的数量是根据最大期望总吞吐量以及键空间中项目的分布得出的。换句话说,如果选择分区键以使其在分区键空间中均匀分布项目,则每个分区最终具有大致相同数量的项目。每个分区中的项目数大约等于表中的项目总数除以分区数。
该文档还指出,每个分区的空间限制为大约 10GB。并且一旦存储在任何分区中的所有项目的大小总和超过 10GB,DynamoDB 将启动一个后台进程,该进程将自动透明地将此类分区分成两半 - 从而产生两个新分区。再一次,如果项目是均匀分布的,这很好,因为每个新的子分区最终将保存原始分区中大约一半的项目。
拆分的一个重要方面是拆分分区的吞吐量将是原始分区可用吞吐量的一半。
到目前为止,我们已经介绍了快乐的情况。
另一方面,可能有一个或几个分区键值对应于大量项目。如果表架构使用排序键并且多个项目散列到相同的分区键,则通常会发生这种情况。在这种情况下,单个分区键可能会负责占用超过 10 GB 的项目。这将导致分裂。在这种情况下,DynamoDB 仍将创建两个新分区,但它不会仅使用分区键来决定应将项目存储在哪个子分区中,它还将使用排序键。
例子
不失一般性并使事情更容易推理,假设有一个表,其中分区键是字母 (AZ),数字用作排序键。
假设该表有大约 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 | | |
+-----------------+----------------+---------------+---------------+-- ..
请注意,对于大多数分区键值,表中有 1 到 3 个项目,但有两个分区键值:D
并且F
看起来不太好。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))
我希望这有助于可视化项目通常基于通过将散列函数应用于其分区键值而获得的散列值映射到分区,但如果需要,被散列的值可以包括分区键 + 排序键值出色地。