NoSQLデータベース入門!DynamoDBで高速・柔軟なデータストアを体験
こんにちは!現役エンジニアのakrです。
「【AWSプロフェッショナルへの道】現役エンジニアが贈るクラウド実践ガイド」の第8回をお届けします。前回はRDSでリレーショナルデータベースを構築し、Webアプリケーションの基盤をさらに強化しましたね。
今回は、これまでのリレーショナルデータベース(RDB)とは異なる特性を持つデータベース、NoSQLデータベースに焦点を当てます。特に、AWSが提供するフルマネージドなNoSQLサービス、Amazon DynamoDBを徹底的に解説します。
「RDBで十分じゃないの?」「NoSQLって何が違うの?」といった疑問を持つかもしれません。DynamoDBは、RDBでは難しい極めて高いスケーラビリティと低レイテンシーが求められるアプリケーションに最適です。本記事では、NoSQLの基本概念から、DynamoDBの特徴、テーブルの作成、データの操作、そして基本的な設計思想までを網羅的に学び、実践的なNoSQLデータストアの構築スキルを身につけましょう。
1. NoSQLデータベースとは?RDBとの違い
まず、NoSQLとは何か、そしてなぜRDBと異なるのかを理解しましょう。
「NoSQL」は「Not only SQL」の略であり、リレーショナルデータベース(RDB)以外のデータベースを指す総称です。RDBは厳格なスキーマ(データの構造)を持ち、SQLを使ってデータを操作しますが、NoSQLはより柔軟なデータモデルと、特定のユースケースに特化した性能向上を追求しています。
RDBとNoSQLの比較
| 特徴 | リレーショナルデータベース (RDB) | NoSQLデータベース |
|---|---|---|
| データモデル | 表形式(行と列)、厳格なスキーマ | キーバリュー、ドキュメント、カラム指向、グラフなど |
| スケーラビリティ | 垂直スケーリング(スケールアップ)が主。水平スケーリングは複雑 | 水平スケーリング(スケールアウト)が容易 |
| 整合性 | ACID特性(原子性、一貫性、独立性、永続性)を保証 | BASE特性(結果整合性)が主。柔軟性と可用性を優先 |
| 用途 | 複雑なトランザクション、データの整合性が最重要 | 大規模データ、高スループット、低レイテンシー、柔軟なスキーマ |
| 例 | MySQL, PostgreSQL, Oracle, SQL Server | DynamoDB, MongoDB, Cassandra, Redis |
なぜNoSQLが必要なのか?
現代のWebアプリケーションやIoT、モバイルアプリなどは、RDBが想定していなかったような大規模なデータ量と超高速なアクセス要求に直面しています。例えば、数億ユーザーが利用するSNSのフィード表示や、リアルタイムなゲーミングデータ、数百万台のIoTデバイスからのデータ収集などです。
このようなシナリオにおいて、RDBのスケールアウトの難しさや、厳格なスキーマが開発速度を低下させる可能性があります。NoSQLは、これらの課題に対応するために進化してきました。
2. Amazon DynamoDBとは?フルマネージドNoSQL
Amazon DynamoDBは、AWSが提供するフルマネージドなNoSQLキーバリューおよびドキュメントデータベースです。その最大の特徴は、どのような規模でも1桁ミリ秒のパフォーマンスを実現するように設計されている点です。
DynamoDBの主な特徴
- フルマネージド: サーバーのプロビジョニング、パッチ適用、バックアップ、復元、スケーリングなど、運用管理のほとんどをAWSが代行します。運用負荷を大幅に削減できます。
-
高速性とスケーラビリティ:
- ミリ秒単位の応答速度を維持しながら、1日に数兆のリクエストを処理し、数百万TPS (Transactions Per Second) をサポートできます。
- データ量やスループットに応じて、自動的にスケールアウト/インします。
-
高可用性と耐久性:
- データは複数のアベイラビリティゾーン (AZ) にわたって自動的に複製され、非常に高い可用性(99.999%)と耐久性(イレブンナイン)を誇ります。
- 柔軟なスキーマ: RDBのような厳格なスキーマ定義が不要で、データモデルを柔軟に変更できます。新しい属性(列)をアイテム(行)に追加するのも簡単です。
- サーバーレス統合: AWS Lambdaなどのサーバーレスサービスと非常に親和性が高く、モダンなアーキテクチャに適しています。
- セキュリティ: 保存時の暗号化、IAMによるきめ細かいアクセス制御、VPCエンドポイントなど、高いセキュリティを提供します。
-
コスト効率:
- 使用したリソースに対してのみ料金が発生する従量課金制です。
- オンデマンドキャパシティモードやプロビジョニング済みキャパシティモードを選択でき、アクセスパターンに合わせてコストを最適化できます。
3. DynamoDBの主要な構成要素と概念
DynamoDBのテーブルを作成・操作する上で理解すべき重要な概念を見ていきましょう。
3.1. テーブル (Table)
DynamoDBの「テーブル」は、データのコレクションです。RDBのテーブルに似ていますが、行と列が厳格に定義されているわけではありません。
3.2. アイテム (Item)
テーブルに格納される個々のデータレコードです。RDBの「行」に相当しますが、各アイテムは異なる属性(列)を持つことができます。JSON形式で表現されます。
3.3. 属性 (Attribute)
アイテムを構成する個々のデータ要素です。RDBの「列」に相当しますが、データ型は柔軟で、入れ子になった構造(リストやマップ)もサポートします。
3.4. プライマリキー (Primary Key)
テーブル内の各アイテムを一意に識別するための属性です。プライマリキーは、データへの高速なアクセスを可能にするDynamoDBの最も重要な要素です。プライマリキーには2つのタイプがあります。
-
パーティションキー (Partition Key):
- 単一の属性で構成されるプライマリキーです。
- DynamoDBがデータを物理的に分散(パーティション化)するために使用します。データの均一な分散と高速なアクセスを実現するために、カーディナリティ(値の多様性)が高い属性を選択することが重要です。
-
パーティションキーとソートキーの複合キー (Composite Primary Key):
- パーティションキーとソートキーの2つの属性で構成されるプライマリキーです。
- 同じパーティションキーを持つアイテムは、ソートキーの値に基づいてソートされて保存されます。
- 特定のパーティションキー内での範囲クエリ(例: あるユーザーの最新10件の投稿)に非常に有効です。
3.5. セカンダリインデックス (Secondary Index)
プライマリキー以外の属性でクエリを実行したい場合に作成します。
-
グローバルセカンダリインデックス (GSI):
- テーブルとは異なるパーティションキーとソートキーを持つインデックスです。
- 完全に独立したストレージとスループットを持つため、強力なクエリ機能を提供しますが、コストや整合性に注意が必要です(結果整合性)。
-
ローカルセカンダリインデックス (LSI):
- テーブルと同じパーティションキーと、異なるソートキーを持つインデックスです。
- テーブルと同じパーティションに保存され、同一パーティション内でのクエリに利用できます(強い整合性)。
3.6. 読み込み/書き込みキャパシティユニット (Read/Write Capacity Unit - RCU/WCU)
DynamoDBは、データ操作のスループットをキャパシティユニットで管理します。
-
読み込みキャパシティユニット (RCU):
- 1 RCU: 1秒あたり最大1回の強力な整合性のある読み込み、または2回の結果整合性のある読み込み(それぞれ最大4KBのアイテム)を実行できます。
-
書き込みキャパシティユニット (WCU):
- 1 WCU: 1秒あたり最大1回の書き込み(最大1KBのアイテム)を実行できます。
キャパシティモードは2種類あります。
- プロビジョニング済み: 事前に必要なRCU/WCUをプロビジョニングします。料金はプロビジョニングしたキャパシティに対して発生します。アクセスパターンが予測可能な場合に適しています。
- オンデマンド: 実際の読み込み/書き込みリクエスト数に応じて自動的にキャパシティを調整します。料金は実際に処理されたリクエスト数に基づいて発生します。アクセスパターンが予測できない場合や、アクセスが非常に少ない/多い場合に適しています。初期学習にはオンデマンドモードが推奨されます。
4. 実践!DynamoDBテーブルを作成し、データを操作しよう
それでは、実際にAWSマネジメントコンソールを使ってDynamoDBテーブルを作成し、基本的なデータの操作を行ってみましょう。今回は、シンプルなユーザー情報テーブルを作成します。
4.1. DynamoDBテーブルの作成
- AWSマネジメントコンソールにサインインし、「DynamoDB」サービスに移動します。
- 左のナビゲーションペインから「テーブル」を選択し、「テーブルの作成」をクリックします。
-
テーブル名:
Users -
プライマリキー:
-
パーティションキー:
UserId(データ型: 文字列) -
ソートキー: (今回はなし。必要であれば
CreatedAtなど)
-
パーティションキー:
-
テーブル設定:
- デフォルト設定を使用: チェックを外します。
- キャパシティモード: 「オンデマンド」を選択します。(無料枠対象であり、アクセスパターンを気にせず使えるため推奨)
- 暗号化: デフォルトのままでOKです。
- 「テーブルの作成」をクリックします。
テーブルの作成には数秒〜数十秒かかります。ステータスが「アクティブ」になるまで待ちましょう。
4.2. アイテムの作成 (データの追加)
作成したUsersテーブルにデータを追加してみましょう。
- 作成した
Usersテーブルを選択します。 - 「項目」タブをクリックし、「項目を作成」をクリックします。
- 初期状態ではプライマリキー(
UserId)のみが表示されます。他の属性を追加するには「新規属性を追加」をクリックします。-
UserId:
user-001(文字列) -
新規属性を追加→「文字列」を選択し、名前を
UserName、値をAliceと入力 -
新規属性を追加→「数値」を選択し、名前を
Age、値を30と入力 -
新規属性を追加→「ブール」を選択し、名前を
IsActive、値をtrueと入力 -
新規属性を追加→「マップ」を選択し、名前を
Addressと入力し、その中にCity: Tokyo(文字列),Zip: 100-0001(文字列) などを追加します。
-
UserId:
- 「項目を作成」をクリック。
同様の手順で、いくつか項目を追加してみましょう。スキーマが柔軟なので、新しい項目では別の属性を追加することもできます(例: user-002にはEmail属性を追加するが、Address属性は追加しない、など)。
4.3. アイテムの読み込み (データの取得)
追加したデータを取得してみましょう。プライマリキーを使ってアイテムを取得します。
-
Usersテーブルの「項目」タブで、「クエリ」または「スキャン」を選択します。 - 「クエリ」を選択し、プライマリキーの
UserIdにuser-001と入力します。 - 「実行」をクリックすると、
user-001の全データが表示されます。
4.4. アイテムの更新
既存のデータを更新してみましょう。
-
Usersテーブルの「項目」タブで、更新したいアイテム(例:user-001)を選択します。 - 右上の「アクション」→「項目を編集」をクリックします。
-
Ageを31に変更したり、新しい属性(例:LastLoginDate)を追加したりできます。 - 「変更を保存」をクリック。
4.5. アイテムの削除
不要なデータを削除してみましょう。
-
Usersテーブルの「項目」タブで、削除したいアイテム(例:user-001)を選択します。 - 右上の「アクション」→「項目を削除」をクリックします。
- 確認ダイアログで「削除」をクリック。
5. DynamoDBの設計思想とベストプラクティス
RDBとは異なるNoSQLの特性を最大限に活かすためには、DynamoDB特有の設計思想を理解することが重要です。
5.1. アクセスパターン駆動設計
RDBでは、まずエンティティ(ユーザー、商品など)を定義し、その後のクエリに合わせてインデックスを追加していくのが一般的です。しかし、DynamoDBでは最初にアプリケーションのアクセスパターン(どのようなクエリを実行するか)を明確にし、それに基づいてプライマリキーとインデックスを設計します。
-
例:
- 「特定のユーザーの全ての投稿を取得したい」→
UserIdをパーティションキー、Timestampをソートキーとする。 - 「特定の商品に紐づく全てのレビューを取得したい」→
ProductIdをパーティションキー、ReviewIdをソートキーとする。 - 「全ユーザーの最新のログイン日時でソートしたい」→
Global Secondary Indexを検討。
- 「特定のユーザーの全ての投稿を取得したい」→
5.2. カーディナリティの高いパーティションキー
パーティションキーは、データをDynamoDBの物理パーティションに均一に分散させるために非常に重要です。
- ホットパーティションの回避: 特定のパーティションにアクセスが集中する「ホットパーティション」が発生すると、スループットがボトルネックになります。これを避けるために、読み込み/書き込みリクエストが均等に分散されるような、カーディナリティ(値の多様性)が高い属性をパーティションキーに選択しましょう。
- UUIDのようなランダムな値をパーティションキーとして利用することも有効です。
5.3. データの非正規化と重複
RDBではデータの正規化が推奨されますが、DynamoDBではクエリ性能向上のために、意図的にデータを非正規化したり、重複させたりすることがあります。
- 例えば、ユーザー名と投稿内容を別のテーブルに持つのではなく、投稿アイテムの中にユーザー名を埋め込むことで、ユーザー名を取得するための追加クエリをなくし、読み込み性能を向上させることができます。
5.4. スキーマの柔軟性を活かす
DynamoDBは柔軟なスキーマを持つため、新しい属性を簡単に追加できます。これは、アジャイル開発や、データ構造が頻繁に変わるアプリケーションに非常に適しています。
5.5. コスト管理
- オンデマンドキャパシティモード: 初期開発やアクセスが予測できない場合に最適です。
- プロビジョニング済みキャパシティモード: アクセスパターンが安定しており、一定のスループットが予測できる場合に、コストを抑えられます。Auto Scalingと組み合わせて、動的にキャパシティを調整することも可能です。
- 使用しなくなったテーブルやインデックスは、必ず削除しましょう。
まとめ
今回は、NoSQLデータベースの基本概念から、AWSのフルマネージドNoSQLサービスであるAmazon DynamoDBについて、その特徴、テーブルとアイテムの操作、そして重要な設計思想までを学びました。
- NoSQLは、RDBとは異なる柔軟なデータモデルと、水平スケーリングによる極めて高いスケーラビリティと低レイテンシーが特徴です。
- DynamoDBは、これらのNoSQLのメリットをAWSのフルマネージドサービスとして提供し、サーバー管理の負担をなくします。
- プライマリキー(パーティションキー、ソートキー)、セカンダリインデックス、キャパシティユニットがDynamoDBの主要な構成要素です。
- アクセスパターン駆動設計を理解し、カーディナリティの高いパーティションキーを選ぶことが、DynamoDBの性能を最大限に引き出す鍵です。
- 実際にDynamoDBテーブルの作成から、アイテムの追加・読み込み・更新・削除までを実践しました。
DynamoDBは、大規模なWebサービスやモバイルバックエンド、IoTデータ処理などで非常に強力な選択肢となります。RDBとは異なる考え方が必要ですが、その特性を理解し適切に設計することで、これまでにない高性能でスケーラブルなアプリケーションを構築できるようになるでしょう。
この記事が皆さんのAWS学習の一助となれば幸いです。
もしこの記事が役に立ったと感じたら、ぜひ「いいね」👍をお願いします!励みになります!
