UUID v4は、ランダム性が高く衝突の心配が少ないため、分散システムでよく使われる識別子です。
しかし、DynamoDBの主キーとして使うと、見落としがちなコストやストレージの影響が生じます。
特に、UUID v4は128ビット(通常は36文字の文字列)と比較的大きく、かつ完全にランダムなため、パーティションキーとして使うとパーティションの偏りやストレージ効率の低下につながる可能性があります。
DynamoDBの料金は、主にプロビジョンドキャパシティ(RCU/WCU)とストレージ容量に依存します。
UUID v4をそのまま主キーにすると、以下のようなコスト面の懸念が生じます。
- パーティションキーが完全ランダムになり、アクセスパターンが均一になりすぎて、DynamoDBの自動スケーリングやホットパーティション対策の恩恵を受けにくくなる
- キーが長いため、インデックスやGSI、LSIを含めたストレージ使用量が増え、ストレージ料金が長期的に増える
- スキャンやクエリの際に、キーサイズが大きい分だけ読み取りユニット(RCU)の消費がわずかに増える可能性がある
ただし、UUID v4を使うこと自体が悪いわけではありません。
分散環境での一意性確保や、セキュリティ上の理由(推測されにくいID)から、UUID v4を採用するメリットも大きいです。
問題は「そのまま使う」か「工夫して使うか」という設計の差にあります。
そこで本記事では、UUID v4をDynamoDBの主キーに使いつつも、ストレージ容量と料金をできるだけ抑えるための工夫を、いくつかの観点から整理します。
- パーティションキーの設計を見直し、UUID v4をそのまま使うのではなく、プレフィックスや時間ベースの接頭辞を付けてアクセスパターンを制御する
- キーをそのまま文字列で保存するのではなく、バイナリ形式(例:Base64やバイナリ属性)で圧縮してストレージ使用量を削減する
- 必要に応じて、より短いID(ULIDやカスタムID)と組み合わせて、UUID v4を補助的な識別子として使う設計を検討する
- DynamoDBの料金モデルを理解し、RCU/WCUとストレージのどちらがボトルネックになりやすいかを事前に評価する
これらの工夫を組み合わせることで、UUID v4の利点を維持しつつ、DynamoDBのストレージコストと運用コストを現実的な範囲に抑えることができます。
以下では、具体的な設計例とコストの試算イメージも交えながら、実践的なチューニング方法を解説します。
DynamoDBの料金モデルを理解する:RCU/WCUとストレージの基本

DynamoDBの料金は、主にプロビジョンドキャパシティ(RCU/WCU)とストレージ容量の2つの軸で決まります。
RCU(Read Capacity Unit)は1秒あたりの読み取り能力、WCU(Write Capacity Unit)は1秒あたりの書き込み能力を表します。
1 RCUは1秒あたり最大4KBの強力な整合性読み取り、または2倍の8KBの結果整合性読み取りに対応します。
一方、1 WCUは1秒あたり最大1KBの書き込みを処理できます。
プロビジョンドモードでは、事前にRCU/WCUを設定し、その分だけ料金が発生します。
オンデマンドモードでは、実際のリクエスト量に応じて自動的にスケールし、読み書きの回数とデータ量に基づいて課金されます。
どちらのモードでも、アイテムサイズが大きいほど1回の読み書きで消費するRCU/WCUが増える点は共通です。
ストレージ料金は、テーブルに保存されているデータの総量に対して課金されます。
DynamoDBは内部でデータを圧縮しますが、ユーザーが指定する属性名や属性値の長さがそのままストレージ使用量に影響します。
特に、主キーやソートキー、GSI/ LSIのキー属性は、すべてのアイテムに必ず含まれるため、キーが長いとストレージ料金が積み上がりやすいという特徴があります。
UUID v4とは何か?構造と特性を整理
UUID(Universally Unique Identifier)v4は、128ビットの識別子をランダムに生成する仕様です。
通常は32桁の16進数(各4ビット)をハイフンで区切った36文字の文字列として表現されます。
例として、以下のような形式です。
550e8400-e29b-41d4-a716-446655440000
このうち、バージョンを示す4ビット(上記例の4の部分)とバリアントを示す2ビットを除いた122ビットがランダムに生成されます。
そのため、理論上は衝突確率が極めて低く、分散システムで一意なIDを生成するのに適しています。
一方で、UUID v4は完全にランダムであるため、時系列情報を持たず、単純に比較しても順序が意味を持ちません。
また、128ビットをそのまま文字列として扱うと、32バイト(16進数表現)〜36バイト(ハイフン付き)と、一般的な整数型のID(例:8バイトのbigint)に比べてキーサイズが大きくなりがちです。
UUID v4を主キーにしたときのストレージへの影響
DynamoDBでUUID v4を主キー(パーティションキー、あるいはパーティションキー+ソートキー)として使う場合、ストレージへの影響は無視できません。
主キーはすべてのアイテムに必ず含まれ、さらにGSIやLSIでも繰り返し保存されるためです。
たとえば、主キーが36文字のUUID v4文字列だとします。
1アイテムあたりの主キーだけで36バイト前後を消費します。
これに加えて、GSIやLSIで同じUUIDをキーとして使うと、インデックス側でも同じ36バイトが繰り返し保存されます。
テーブルに1,000万件のアイテムがあり、GSIが1本あると仮定すると、キーだけでおおよそ次のようなストレージ使用量になります。
- テーブル本体:1,000万 × 36バイト ≈ 360MB
- GSI:1,000万 × 36バイト ≈ 360MB
- 合計:720MB
これはあくまでキー部分だけの概算ですが、実際には他の属性も加わるため、ストレージ料金が想定より増えやすいことがわかります。
また、DynamoDBの読み書きはアイテム全体のサイズに基づくため、キーが長いとRCU/WCUの消費もわずかに増加します。
このように、UUID v4をそのまま主キーに使うと、一意性やセキュリティ面でのメリットはあるものの、ストレージ使用量と料金の面で不利になりやすいというトレードオフが生じます。
そのため、UUID v4を使う場合でも、キー圧縮や設計の工夫によってストレージ負荷を抑えることが重要になります。
DynamoDBのパーティションキー設計とUUID v4の相性

DynamoDBのパーティションキー設計は、パフォーマンスとスケーラビリティに直結する重要な要素です。
DynamoDBは、パーティションキーのハッシュ値に基づいてデータを物理的なパーティションに分散します。
そのため、特定のパーティションキー値にアクセスが集中すると「ホットパーティション」が発生し、スループットの上限に達しやすくなります。
一般的に、パーティションキーは以下のような性質が求められます。
- アクセスが特定の値に偏らない(均等に分散する)
- 将来のデータ増加を見越して、十分なカーディナリティ(取りうる値の種類)を持つ
- 業務上のアクセスパターンに合致している(クエリやスキャンの条件として使いやすい)
UUID v4は、128ビットのランダム値から生成されるため、値の分布がほぼ均一で、カーディナリティも非常に高いという特徴があります。
この性質は、DynamoDBのパーティションキーとして使う場合、アクセスの分散という観点では非常に相性が良いと言えます。
完全ランダムなUUID v4がホットパーティションを生みにくい理由
UUID v4がホットパーティションを生みにくい理由は、その完全なランダム性と高いカーディナリティにあります。
DynamoDBはパーティションキーのハッシュ値を計算し、その値に基づいてデータをパーティションに割り振ります。
UUID v4は値ごとにまったく異なるランダムなビット列を持つため、ハッシュ値も広い範囲に散らばります。
結果として、データが多くのパーティションに均等に分散され、特定のパーティションにアクセスが集中しにくくなります。
これは、たとえば「ユーザーID」や「カテゴリ名」のような、一部の値にアクセスが偏りやすいキーを使う場合と対照的です。
- ユーザーIDが少数の値に集中する場合:特定ユーザーのデータが一つのパーティションに集まり、ホットパーティションになりやすい
- UUID v4を使う場合:各アイテムがランダムなUUIDを持つため、どのパーティションにも均等に散らばりやすい
ただし、UUID v4がホットパーティションを生みにくいというのは、あくまで「キー値の分布」という観点での話です。
実際のアプリケーションでは、アクセスパターン(どのアイテムが頻繁に読み書きされるか)も重要になります。
たとえば、特定のUUIDを持つアイテムだけが極端に頻繁にアクセスされる場合、そのアイテムが属するパーティションには依然として負荷が集中します。
とはいえ、多くのユースケースでは、UUID v4をパーティションキーに使うことで、キー値の偏りによるホットパーティションのリスクを大幅に低減できると言えます。
その一方で、完全ランダムであるがゆえに、時間順のクエリや範囲スキャンがしにくいというデメリットもあります。
このトレードオフを理解した上で、UUID v4をパーティションキーとして採用するかどうかを判断することが重要です。
UUID v4をそのまま主キーにしたときのコスト面の懸念点

UUID v4をDynamoDBの主キーとしてそのまま使う場合、一意性や分散性のメリットはあるものの、料金面での懸念点がいくつか生じます。
特に、主キーはすべてのアイテムに必ず含まれ、GSIやLSIでも繰り返し保存されるため、キーサイズが大きいとRCU/WCUの消費とストレージ料金の両方に影響します。
DynamoDBの料金は、主に以下の要素で決まります。
- プロビジョンドキャパシティ(RCU/WCU)またはオンデマンドでの読み書きリクエスト数
- テーブルおよびインデックスに保存されたデータの総ストレージ量
UUID v4は通常36文字の文字列として扱われ、1アイテムあたり約36バイトを消費します。
このサイズが大きいと、以下のようなコスト面の懸念が生じます。
キーサイズが大きいとRCU/WCUにどう影響するか
DynamoDBの読み取り(GetItem, Query, Scanなど)では、アイテム全体のサイズに応じてRCUが消費されます。
1 RCUは最大4KB(強力な整合性読み取り)または8KB(結果整合性読み取り)に対応します。
つまり、アイテムサイズが大きいほど、1回の読み取りで消費するRCUが増えます。
UUID v4を主キーに使うと、主キーだけで約36バイトを消費します。
これに他の属性が加わるため、アイテム全体のサイズがわずかに増加します。
たとえば、本来は1 RCUで読み取れるサイズのアイテムが、キーが長いために4KBを超えてしまい、2 RCUを消費するようになる可能性があります。
同様に、書き込み(PutItem, UpdateItemなど)でも、アイテム全体のサイズに応じてWCUが消費されます。
1 WCUは1KBまでの書き込みに対応するため、アイテムサイズが大きいほど必要なWCUも増えます。
- キーが短い場合:1アイテムあたりのサイズが小さく、1 RCU/WCUで処理できる範囲に収まりやすい
- UUID v4をそのまま主キーにした場合:キーだけで36バイト消費するため、アイテム全体のサイズが増え、RCU/WCUの消費がわずかに増加する
この影響は1回の操作では微々たるものですが、大量の読み書きが発生するシステムでは、長期的に料金に積み上がる可能性があります。
GSI・LSIを含めたインデックスのストレージコスト増加
DynamoDBでは、テーブル本体に加えて、GSI(グローバルセカンダリインデックス)やLSI(ローカルセカンダリインデックス)を定義できます。
これらのインデックスは、元のテーブルのデータを別のキー順序で再構成したものであり、インデックスごとにストレージが消費されます。
UUID v4を主キーに使う場合、多くの設計ではGSIやLSIでも同じUUIDをキーとして再利用します。
その結果、同じUUIDがテーブル本体と各インデックスで繰り返し保存されることになります。
たとえば、1,000万件のアイテムを持つテーブルがあり、GSIが1本あると仮定します。
主キーが36文字のUUID v4だとすると、ストレージ使用量はおおよそ次のようになります。
- テーブル本体:1,000万 × 36バイト ≈ 360MB
- GSI:1,000万 × 36バイト ≈ 360MB
- 合計:720MB(キー部分のみの概算)
これはあくまでキー部分の計算であり、実際には他の属性も加わるため、ストレージ料金はさらに増加します。
DynamoDBのストレージ料金はGB単位で課金されるため、データ量が大きくなると、月々の料金にも無視できない影響が出てきます。
このように、UUID v4をそのまま主キーに使うと、RCU/WCUの消費がわずかに増える可能性があることに加えて、GSI・LSIを含めたインデックスでのストレージコスト増加という懸念点が生じます。
これらの影響を事前に見積もり、必要に応じてキー圧縮や設計変更を検討することが、コスト最適化の重要なポイントになります。
UUID v4を使いつつストレージを削減する工夫:キー圧縮と設計変更

UUID v4をDynamoDBの主キーとして使う場合、一意性や分散性のメリットは維持しつつ、ストレージ使用量と料金を抑える工夫が重要になります。
ここでは、キーそのものを圧縮する方法と、パーティションキーの設計を工夫する方法の2つの観点から、具体的な対策を整理します。
バイナリ属性やBase64でUUIDを圧縮する方法
UUID v4は本来128ビット(16バイト)のバイナリデータですが、多くの実装では16進数文字列(32文字)やハイフン付きの36文字として扱われます。
この文字列表現をそのままDynamoDBの文字列属性として保存すると、1アイテムあたり32〜36バイトを消費します。
一方、DynamoDBはバイナリ型(B)の属性をサポートしており、16バイトのバイナリデータをそのまま保存できます。
これにより、キーサイズを約半分以下に圧縮できます。
- 文字列表現(36文字):約36バイト
- バイナリ表現(16バイト):16バイト
たとえば、UUID 550e8400-e29b-41d4-a716-446655440000 をバイナリとして保存すると、以下のようなイメージになります(実際のバイト列は実装依存です)
55 0e 84 00 e2 9b 41 d4 a7 16 44 66 55 44 00 00
アプリケーション側では、UUIDを生成・利用する際にバイナリ形式で扱い、DynamoDBにはそのままB型属性として保存します。
必要に応じて、Base64エンコードした文字列(約22〜24文字)として保存する方法もあります。
Base64はバイナリデータをテキストとして扱いやすくしつつ、元の16進数表現より短くできるため、文字列属性として扱いたい場合の妥協案として有効です。
ただし、バイナリ属性やBase64表現は、そのままでは人間が読めないため、デバッグやログ出力の際には元のUUID文字列に戻す処理が必要になります。
また、既存のシステムで文字列UUIDを前提にしている場合、アプリケーション側の変更コストも考慮する必要があります。
プレフィックス付きUUIDでパーティションキーを制御する
UUID v4は完全にランダムであるため、DynamoDBのパーティションキーとして使うと、アクセスが均等に分散されやすくホットパーティションを生みにくいというメリットがあります。
一方で、時系列でのクエリや、特定の範囲に属するデータをまとめて取得したい場合には不向きです。
そこで、プレフィックス付きUUIDという設計が有効です。
これは、UUID v4の前に、何らかの識別子や時間情報を付与する方法です。
たとえば、月単位でデータをまとめたい場合、パーティションキーを以下のように設計します。
2024-01#550e8400-e29b-41d4-a716-446655440000
ここでは、2024-01という年月をプレフィックスとして付け、その後にUUID v4を連結しています。
これにより、以下のようなメリットが得られます。
- 同じ月のデータは同じプレフィックスを持つため、月単位でのクエリやバッチ処理がしやすくなる
- DynamoDBはプレフィックス部分も含めてハッシュ計算するため、月ごとにパーティションが分散されつつ、月内のデータはまとまりやすくなる
- UUID v4部分がランダムであるため、月内でのアクセス分散も維持される
プレフィックスには、以下のような情報が使えます。
- 年月(
2024-01) - テナントIDやユーザーIDのプレフィックス(
tenantA#) - データの種類やカテゴリ(
order#,user#)
この方法は、UUID v4のランダム性による分散メリットを維持しつつ、アクセスパターンに応じたパーティション制御を可能にする点で優れています。
ただし、プレフィックスを付けることでキーがさらに長くなるため、ストレージ使用量が増える可能性もあります。
そのため、プレフィックスの長さは必要最小限に抑え、必要に応じてバイナリ圧縮と組み合わせるなどの工夫が求められます。
これらの工夫を組み合わせることで、UUID v4の利点を活かしつつ、DynamoDBのストレージコストと運用コストを現実的な範囲に抑えることができます。
ULIDやカスタムIDとの組み合わせでUUID v4を補助的に使う

UUID v4をDynamoDBの主キーとしてそのまま使うと、一意性や分散性のメリットはあるものの、ストレージサイズの大きさや時系列でのクエリのしにくさといった課題が生じます。
そこで、ULID(Universally Unique Lexicographically Sortable Identifier)やカスタムIDを主キーとして使い、UUID v4は補助的な識別子として扱う設計が有効です。
このアプローチのポイントは、主キーには短くてソート可能なID(ULIDなど)を使い、UUID v4は必要に応じて別属性として保持することです。
これにより、DynamoDBのストレージコストを抑えつつ、UUID v4の利点(一意性・ランダム性)も活かせます。
ULIDの構造とDynamoDBでの利用メリット
ULIDは、128ビットの識別子を時間ベースのプレフィックス+ランダムなサフィックスという構造で表現します。
具体的には、先頭48ビットがミリ秒単位のタイムスタンプ、残り80ビットがランダムな値です。
文字列表現は26文字のBase32文字列で、以下のような形式になります。
01ARZ3NDEKTSV4RRFFQ69G5FAV
この構造により、ULIDには以下の特徴があります。
- 時系列でソート可能:先頭のタイムスタンプ部分が時間順に並ぶため、生成順に並べ替えができる
- 衝突確率が低い:80ビットのランダム部分により、UUID v4と同様に衝突確率は極めて低い
- 文字列表現が比較的短い:26文字と、UUID v4の36文字より短く、ストレージ効率が良い
DynamoDBでULIDを主キーとして使う場合、以下のようなメリットがあります。
- 主キーが26文字と短いため、テーブル本体やGSI/LSIのストレージ使用量を抑えられる
- 時系列でソート可能なため、「最新のデータを取得する」「ある期間のデータをまとめてクエリする」といった操作がしやすい
- ランダム部分があるため、アクセスがある程度分散され、ホットパーティションを生みにくい
ただし、ULIDはタイムスタンプに依存するため、システム時刻が巻き戻ると重複や順序の乱れが生じるリスクがあります。
また、UUID v4ほど完全にランダムではないため、アクセスパターンによっては偏りが生じる可能性もあります。
UUID v4とULIDを併用したハイブリッド設計の例
UUID v4とULIDを併用するハイブリッド設計では、主キーにはULIDを使い、UUID v4は別属性として保持するのが典型的です。
これにより、主キーは短くソート可能になり、UUID v4は必要に応じて外部システムとの連携やセキュリティ上の識別子として利用できます。
たとえば、注文情報を管理するテーブルを考えます。
DynamoDBのアイテム構造は以下のようになります。
{
"orderId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", // ULID(主キー)
"orderUuid": "550e8400-e29b-41d4-a716-446655440000", // UUID v4(補助属性)
"userId": "user123",
"amount": 5000,
"createdAt": "2024-01-15T10:30:00Z"
}
この設計では、以下のようなメリットがあります。
- 主キー
orderIdはULIDのため、26文字で済み、ストレージ効率が良い orderIdでクエリすると、生成順に近い順序でデータが取得できる- UUID v4は
orderUuid属性として保持するため、外部APIや他システムとの連携でUUIDを要求される場合にも対応できる - UUID v4を主キーにしないため、GSIやLSIでのキー重複によるストレージ増加を抑えられる
さらに、アクセスパターンに応じてGSIを設計することもできます。
たとえば、ユーザーごとの注文を時系列で取得したい場合、以下のようなGSIを定義します。
- GSIパーティションキー:
userId - GSIソートキー:
orderId(ULID)
これにより、userIdでクエリすると、そのユーザーの注文が時系列順に並んだ状態で取得できます。
ULIDがソートキーとして機能するため、追加のタイムスタンプ属性をソートキーにしなくても済みます。
このように、ULIDを主キーやソートキーとして使い、UUID v4は補助的な識別子として扱うことで、DynamoDBのストレージコストとクエリのしやすさを両立できます。
UUID v4を完全に排除するのではなく、役割を分けて使い分けることが、コスト最適化と設計の柔軟性を高める鍵になります。
DynamoDBの料金最適化のための設計パターン集

DynamoDBの料金を最適化するには、データモデル設計とキャパシティ管理の両面からアプローチする必要があります。
データモデル設計では、パーティションキーやGSI/LSIの設計によってストレージ使用量とアクセス効率を最適化します。
キャパシティ管理では、RCU/WCUの見積もりと自動スケーリングの活用によって、過剰なプロビジョニングや不足を防ぎます。
ここでは、特にアクセスパターンに応じたパーティションキー設計とRCU/WCUの見積もり・自動スケーリングの活用に焦点を当て、料金最適化のための設計パターンを整理します。
アクセスパターンに応じたパーティションキー設計の例
パーティションキー設計は、DynamoDBの料金とパフォーマンスに直結します。
基本的な考え方は、「どのようなクエリをどのくらいの頻度で実行するか」というアクセスパターンを事前に分析し、それに合ったキー設計を行うことです。
代表的なアクセスパターンと、それに対応するパーティションキー設計の例を以下に示します。
| アクセスパターン | 推奨されるパーティションキー設計 | メリット | 注意点 |
|---|---|---|---|
| ユーザーごとのデータ取得(例:ユーザーの注文一覧) | userId をパーティションキー、orderId や createdAt をソートキー |
ユーザー単位でのクエリが高速。GSIで他の軸(例:商品別)も追加可能 | 特定ユーザーのデータが極端に多い場合、ホットパーティションのリスクあり |
| 時系列でのデータ取得(例:最新のログを取得) | 年月プレフィックス+ランダムID(例:2024-01#ULID) |
時系列での範囲クエリがしやすい。月ごとにパーティションが分散 | プレフィックスが長くなるとストレージ使用量が増える |
| カテゴリ別のデータ取得(例:商品カテゴリ別の一覧) | categoryId をパーティションキー、productId をソートキー |
カテゴリ単位でのクエリが高速。GSIで価格や人気度でのソートも可能 | 人気カテゴリにアクセスが集中するとホットパーティションのリスク |
これらの設計では、GSI(グローバルセカンダリインデックス)を併用することで、複数のアクセスパターンに対応できます。
たとえば、ユーザー別の注文一覧と商品別の売上集計の両方が必要な場合、以下のようにGSIを設計します。
- テーブル本体:
userId(PK)、orderId(SK) - GSI1:
productId(PK)、createdAt(SK)…商品別の売上集計用 - GSI2:
userId(PK)、status(SK)…ユーザー別の注文ステータス確認用
GSIは追加のストレージとRCU/WCUを消費するため、本当に必要なアクセスパターンに限定して設計することが料金最適化のポイントです。
RCU/WCUの見積もりと自動スケーリングの活用
RCU/WCUの見積もりは、プロビジョンドモードでの料金に大きく影響します。
基本的な考え方は、「1秒あたりの読み書き回数」と「1アイテムあたりの平均サイズ」から必要なキャパシティを計算することです。
読み取り(RCU)の見積もり例を以下に示します。
- 1秒あたりの読み取りリクエスト数:100回
- 1アイテムあたりの平均サイズ:2KB
- 強力な整合性読み取りを使用する場合:1 RCUで4KBまで対応
- 必要なRCU:100回 × (2KB / 4KB) = 50 RCU
書き込み(WCU)の見積もり例は以下の通りです。
- 1秒あたりの書き込みリクエスト数:50回
- 1アイテムあたりの平均サイズ:1.5KB
- 1 WCUで1KBまで対応
- 必要なWCU:50回 × (1.5KB / 1KB) = 75 WCU
このように、ピーク時のトラフィックを基準に見積もることが重要です。
ただし、実際のトラフィックは時間帯やイベントによって変動するため、常にピーク値でプロビジョニングすると料金が高くなりがちです。
そこで、自動スケーリングを活用します。
自動スケーリングは、CloudWatchメトリクスに基づいてRCU/WCUを自動的に増減させる機能です。
たとえば、以下のような設定が考えられます。
- ターゲット使用率:70%(RCU/WCUの使用率が70%を超えたらスケールアップ)
- スケールアップの最大値:現在の2倍
- スケールダウンの最小値:ベースラインのRCU/WCU
これにより、ピーク時には自動的にキャパシティが増え、閑散時には最小限に抑えられるため、料金を最適化できます。
ただし、スケールアップには数分のラグがあるため、急激なトラフィック増加には対応しきれない場合もあります。
そのため、予測可能なイベント(キャンペーンやリリースなど)は事前に手動でキャパシティを調整することも重要です。
これらの設計パターンを組み合わせることで、DynamoDBの料金を抑えつつ、パフォーマンスと可用性を両立することが可能になります。
実践的なコスト試算:UUID v4あり/なしの比較シミュレーション

理論的な説明だけでは、UUID v4をDynamoDBの主キーに使うことのコスト影響を実感しにくいかもしれません。
そこで、具体的なサンプルテーブル設計とアイテムサイズの見積もりに基づいて、UUID v4あり/なしのシナリオで月間ストレージ料金とRCU/WCU料金を比較してみます。
このシミュレーションでは、あくまで概算であり、実際の料金はリージョンや利用モード(プロビジョンド/オンデマンド)によって変動します。
しかし、設計の違いがどの程度料金に影響するかを定量的に把握するという目的には十分役立ちます。
サンプルテーブル設計とアイテムサイズの見積もり
まず、シンプルな注文情報を管理するテーブルを想定します。
属性は以下の通りとします。
orderId:主キー(UUID v4あり/なしで形式が変わる)userId:ユーザーID(12文字程度の文字列)amount:注文金額(数値)createdAt:作成日時(ISO8601形式の文字列、24文字程度)
UUID v4ありの場合、orderIdは36文字の文字列とします。
UUID v4なしの場合、orderIdは8バイトの数値(bigint相当)とします。
DynamoDBでは内部的に属性名や型情報も保存されるため、実際のアイテムサイズはこれより大きくなりますが、ここではキー部分の違いに焦点を当てた概算とします。
各属性のサイズを以下のように仮定します。
| 属性名 | データ型 | サイズ(UUID v4あり) | サイズ(UUID v4なし) |
|---|---|---|---|
orderId |
文字列(PK) | 36バイト | 8バイト(数値として扱う場合の概算) |
userId |
文字列 | 12バイト | 12バイト |
amount |
数値 | 8バイト | 8バイト |
createdAt |
文字列 | 24バイト | 24バイト |
| 合計 | – | 80バイト | 52バイト |
このように、UUID v4を主キーに使う場合、1アイテムあたり約28バイト(80 – 52)多く消費することになります。
アイテム数が増えるほど、この差がストレージ料金に積み上がります。
月間ストレージ料金とRCU/WCU料金の比較シナリオ
次に、このテーブルに1,000万件のアイテムが保存されていると仮定し、月間のストレージ料金を比較します。
DynamoDBのストレージ料金はリージョンによって異なりますが、ここでは1GBあたり0.25 USD/月という概算値を使います(実際の料金はAWSの公式ページで確認してください)
まず、ストレージ使用量を計算します。
- UUID v4あり:1,000万 × 80バイト = 800,000,000バイト ≈ 0.745 GB
- UUID v4なし:1,000万 × 52バイト = 520,000,000バイト ≈ 0.484 GB
月間ストレージ料金は以下のようになります。
- UUID v4あり:0.745 GB × 0.25 USD ≈ 0.186 USD/月
- UUID v4なし:0.484 GB × 0.25 USD ≈ 0.121 USD/月
- 差額:約0.065 USD/月
この例では、ストレージ料金の差は月あたり0.065 USDと小さく見えます。
しかし、これはあくまでキー部分のみの計算です。
実際には他の属性やGSI/LSIも加わるため、データ量が大きくなるほど差も拡大します。
次に、RCU/WCU料金への影響を考えます。
プロビジョンドモードで、1秒あたり100回の読み取り(強力な整合性)と50回の書き込みがあると仮定します。
1アイテムあたりの平均サイズは、UUID v4ありで80バイト、なしで52バイトです。
読み取り(RCU)の必要キャパシティは以下の通りです。
- UUID v4あり:100回 × (0.08KB / 4KB) ≈ 2 RCU
- UUID v4なし:100回 × (0.052KB / 4KB) ≈ 1.3 RCU → 実務上は2 RCUに切り上げることが多い
書き込み(WCU)の必要キャパシティは以下の通りです。
- UUID v4あり:50回 × (0.08KB / 1KB) = 4 WCU
- UUID v4なし:50回 × (0.052KB / 1KB) ≈ 2.6 WCU → 実務上は3 WCUに切り上げ
RCU/WCUの単価もリージョンやモードによって異なりますが、ここでは1 RCUあたり0.00013 USD/時間、1 WCUあたり0.00065 USD/時間という概算値を使います(実際の料金はAWS公式を参照してください)
1か月(720時間)として計算すると、月間のRCU/WCU料金は以下のようになります。
- UUID v4あり:RCU 2 × 0.00013 × 720 ≈ 0.187 USD、WCU 4 × 0.00065 × 720 ≈ 1.872 USD、合計 ≈ 2.059 USD/月
- UUID v4なし:RCU 2 × 0.00013 × 720 ≈ 0.187 USD、WCU 3 × 0.00065 × 720 ≈ 1.404 USD、合計 ≈ 1.591 USD/月
- 差額:約0.468 USD/月
このシナリオでは、RCU/WCU料金の差がストレージ料金の差より大きいことがわかります。
特に書き込みが多いシステムでは、WCUの差がそのまま料金に反映されます。
まとめると、UUID v4を主キーに使う場合、ストレージ料金だけでなくRCU/WCU料金にもわずかながら影響が出ます。
データ量やトラフィックが大きくなるほど、この差は無視できない規模になります。
そのため、UUID v4を使う場合でも、キー圧縮や設計変更によってアイテムサイズを抑えることが、長期的なコスト最適化につながると言えます。
まとめ:UUID v4をDynamoDBの主キーに使うときの設計指針とコスト最適化

UUID v4をDynamoDBの主キーとして使うかどうかは、一意性・分散性のメリットとストレージ・料金面のデメリットのトレードオフをどう評価するかという設計判断になります。
本記事では、DynamoDBの料金モデルとUUID v4の特性を踏まえ、コスト最適化の観点から設計指針を整理してきました。
ここで、主要なポイントをまとめます。
まず、DynamoDBの料金はRCU/WCU(読み書きキャパシティ)とストレージ容量の2つが基本です。
UUID v4は128ビットのランダム識別子であり、通常は36文字の文字列として扱われます。
このキーサイズが大きいことが、コスト面での懸念点になります。
- 主キーはすべてのアイテムに必ず含まれ、GSI/LSIでも繰り返し保存されるため、キーが長いとストレージ使用量が増える
- 読み書きはアイテム全体のサイズに基づいてRCU/WCUを消費するため、キーサイズが大きいとわずかにRCU/WCU消費が増える
- 特に書き込みが多いシステムでは、WCUの増加がそのまま料金に反映される
一方で、UUID v4は完全にランダムであるため、DynamoDBのパーティションキーとして使うとアクセスが均等に分散されやすく、ホットパーティションを生みにくいというメリットもあります。
この特性は、分散システムでの一意性確保やセキュリティ面(推測されにくいID)でも有利です。
そこで、UUID v4を主キーに使う場合の設計指針として、以下のような工夫が有効です。
- キー圧縮:UUID v4をそのまま文字列で保存するのではなく、バイナリ属性(16バイト)やBase64エンコード(約22〜24文字)で圧縮し、ストレージ使用量を削減する
- プレフィックス付きUUID:年月やテナントIDなどのプレフィックスを付けてパーティションキーを設計し、アクセスパターンに応じたクエリ効率と分散性を両立する
- ULIDやカスタムIDとの併用:主キーには短くソート可能なULIDを使い、UUID v4は補助的な識別子として別属性に保持するハイブリッド設計を検討する
- GSI/LSIの設計見直し:本当に必要なアクセスパターンに限定してインデックスを設計し、不要なインデックスによるストレージ増加を防ぐ
また、RCU/WCUの見積もりと自動スケーリングの活用も重要です。
ピーク時のトラフィックを基準にRCU/WCUを見積もりつつ、自動スケーリングで閑散時の無駄を削減することで、料金を最適化できます。
実践的なコスト試算のシミュレーションでは、UUID v4あり/なしでアイテムサイズと月間料金を比較しました。
その結果、データ量やトラフィックが大きくなるほど、キーサイズの差がストレージ料金とRCU/WCU料金の両方に積み上がることが確認できました。
特に書き込みが多いシステムでは、WCUの差が料金に直結します。
最終的な設計指針としては、以下のように整理できます。
- UUID v4をそのまま主キーに使う場合:キー圧縮やプレフィックス設計でストレージとアクセス効率を最適化し、RCU/WCUの見積もりと自動スケーリングでキャパシティを適正化する
- ULIDやカスタムIDを主キーに使う場合:主キーは短くソート可能なIDとし、UUID v4は外部連携やセキュリティ要件がある場合に補助的に使う
- どちらの設計を選ぶか:一意性・分散性・時系列クエリのしやすさ・外部システムとの互換性・セキュリティ要件を総合的に評価して決定する
UUID v4をDynamoDBの主キーに使うこと自体は悪い選択ではありません。
重要なのは、その特性を理解した上で、ストレージと料金への影響を定量的に評価し、設計と運用でコストを最適化することです。
本記事で紹介した設計パターンとコスト試算の考え方を参考に、実際のユースケースに合わせた最適な設計を検討していただければ幸いです。


コメント