DynamoDBのパーティションに気をつけよう

AWS, DynamoDB

はじめに

DynamoDBでは、テーブルを作成する際に読み込みと書き込みのスループット(キャパシティ値)を設定する必要があります。このキャパシティ値によって料金が変わってきますので、実績に基づいて出来るだけ低く設定したいところです。

ただし、キャパシティ値を超えるリクエストが発生しまうと処理に失敗してしまうので、ある程度余裕も持たなければならないというのが難しいところです。

この難しさに加えて、パーティションという厄介な存在が我々を苦しめます。

パーティションの仕様

DynamoDBでは、テーブルに割り当てたキャパシティ値によって、パーティションの分割が行われます。

テーブルを初めて作成するときのパーティション数を求める計算式は以下のとおりです。

1 つのパーティションについて、最大 3,000 の 読み込みキャパシティ値(readCapacityUnit = RCU)または最大 1,000 の書き込みキャパシティ値(writeCapacityUnit = WCU)をサポートしています。

例えばRCU: 1,000、WCU: 1,000で設定した場合、以下のようになります。

設定したキャパシティ値は 1 つのパーティションではサポートしきれないため、各パーティションに均等に分散されます。
上記の例だとパーティションは 2 つなので、各パーティションのキャパシティ値は、RCU: 500、WCU: 500 になります。

キャパシティ変更によるパーティション数の変更

RCU: 1,000、WCU: 1,000 で設定したテーブルに対して、WCU: 2,000 に変更したとします。

この場合、パーティション数が 2 から 3 にならない点に注意が必要です。
既存のパーティションがすべて分割されるので、4つになります。(2 * 2 = 4)
よって、各パーティションのキャパシティ値は、RCU: 250、WCU: 500 になります。

ストレージ容量によるパーティション数の変更

1 つのパーティションには約 10 GBのデータを保持できます。
10 GBを超えると、そのパーティションのみが分割されるため、純粋にパーティションが1つ増えます。

キャパシティの削減は慎重に

ここが重要なのですが、
パーティション数は、キャパシティ値を小さくしても減りません。

RCU: 1,000、WCU: 1,000 で設定したテーブル(パーティション数が 2 つ)に対して、WCU: 500 に変更したとします。

本来は 1 つのパーティションでまかなえる値ですが、パーティション数が減ることはありません。
キャパシティ値は各パーティションに分散されるので、各パーティションのキャパシティ値は、RCU: 500、WCU: 250 になります。

このテーブルについて、片方のパーティションのストレージ容量が 10 GBを超えた場合、さらにややこしくなります。
パーティションは 3 つになりますが、「RCU: 500、WCU: 250」のパーティションが分割されたので、各パーティションのキャパシティは以下のようになります。
[1] RCU: 500、WCU: 250
[2] RCU: 250、WCU: 125
[3] RCU: 250、WCU: 125

このように、各パーティションのキャパシティ値(すなわちスループット、処理能力)が大きく落ちてしまいます。
キャパシティ値を超えるリクエストはないのに、エラーが発生してしまうケースが起きやすくなります。

おわりに

処理が均等に分散されれば理論上は問題ないので、「テーブルのプライマリーキーをランダムかつ均一にリクエストされるような値に設定する」ことが推奨されています。
しかしこの設計にすれば絶対に偏らないという話ではないのが悩ましいところです。

アダプティブキャパシティーが使用されることで、偏ったデータアクセスにも対応できるようになっていますが、未然にスロットリングを防ぐことはできません。

以上のことから、一度上げてしまったキャパシティを下げるのは慎重にならなければなりません。
サービスの安定を優先するのであれば、むやみに減らさないようにしましょう

しかしながら、DynamoDBのコストも無視できるものではありません。
サービスの安定を優先しつつも、できるだけコストを下げることは出来ないものか、、
次の記事へ続きます。

この記事を書いた人

小野 充輝
小野 充輝

BABYMETAL(ゆいちゃん)推しのエンジニアです

AWS, DynamoDB