この記事はAWS Ambassadorのクラウドインテグレーション事業部 MSP開発 高橋 修一さんの監修の下、執筆をしております。

はじめに

「AWSのDynamoDBを使ってみたいけど、設定が難しそう…」と感じていませんか?

この記事では、Serverless Frameworkを使って、コマンド数回で簡単にDynamoDBテーブルをデプロイする方法を、DynamoDBの紹介と併せて解説します。

NoSQLSQLの違いといった基本から、具体的な手順までを網羅。ぜひ最後まで読んでみてください!

Amazon DynamoDBとは?

DynamoDBは、Amazon Web Services (AWS) が提供する、サーバーレスのフルマネージドNoSQLデータベースです。
サーバーの管理や運用の手間が不要で、データ量が増えても一貫した高速パフォーマンスを維持できるように設計されています。これにより、開発者はインフラの心配をすることなく、アプリケーション開発に集中できます。

 

SQLとNoSQLの決定的な違いとは?

データベースには大きく分けてSQLとNoSQLの2種類があります。両者の最も大きな違いは、データの構造の柔軟性にあります。

SQL (リレーショナルデータベース)

例えるなら「緻密な設計書」です。
『特定の場所についての色々な情報』のように、細かい情報の取得を得意としています。

Excelの表のように、あらかじめ決められた「行」と「列」にデータを格納します。
データは正規化という考え方に基づき、重複を避けて複数のテーブルに分割して格納することが多いです。

構造がかっちり決まっているため、複雑な検索やデータの整合性を保つのが得意です。事前に列名やデータの種類(文字列, 数値 など)を厳格に定義する必要があります。

事前準備を怠らないでおくと、メリットとしてデータの一貫性や、整合性が強く保証されます。
その一方で、超負荷時にACID特性(強い一貫性)があるため、データベースに負荷がかかりすぎるということがあったり、
全てのレコード(行)で同じカラム(列)構造が必要なため、下記のように異なるデータタイプでもNULL値で埋める必要があり、スキーマ変更時の柔軟性が低いことが欠点です。
また、新たにカラムを追加するとなるとSQLで別途追加宣言(ADD)してからレコード追加を行い、既存のコードなどを見直す必要があります。

例:様々な動物のデータをSQLで管理する場合

名前 分類 犬種 猫種
ポチ 柴犬 NULL
ミケ NULL ペルシャ
シャンシャン パンダ NULL NULL
パン NULL NULL

NoSQL (非リレーショナルデータベース)

SQLとは対照的に、柔軟なデータ構造を持つのが特徴で、例えるなら「収納ボックス」です。
中身の形やサイズが違っていても自由に入れられるので『データごとに必要な情報を柔軟に持たせる』ことが得意です。

NoSQLはいくつかの種類があり、DynamoDBではKey-Valueモデルとドキュメントデータモデルといわれるモデルをサポートしており、用途に応じて使い分けが可能です。
・Key-Value型: キーの値は一意でなければならない。(例:key:user111 → value:”matsuda”)
・Document型: キーに対して複雑なJSON構造を格納(例:ユーザー情報、商品データなど)

例:同じデータをNoSQL(DynamoDB)で管理する場合

[
    {
        "名前": "ポチ",
        "分類": "犬",
        "犬種": "柴犬"
    },
    {
        "名前":"ミケ",
        "分類": "猫",
        "猫種": "ペルシャ"
    },
    {
        "名前":"シャンシャン",
        "分類": "パンダ"
    },
    {
        "名前":"パン",
        "分類": "猿"
    }
]

SQLの例のように、犬には「犬種」、猫には「猫種」といったように、データの種類ごとに関連する情報だけを持たせることができるため、無駄がなく効率的です。
SQLとは対照的にデータは正規化せず、また1つのテーブルに各データをまとめて格納することが多いです。
この格納方法をすることで、非常に高速な読み書きが可能になります。

ただし、構造が自由な分、SQLほど複雑な条件での検索や削除は得意ではありません。
キー・バリューのキーで一意にレコードを特定は可能ですが、条件をつけての検索や絞り込みはDynamoDBであればパーティションキー、ソートキー、セカンダリインデックスといった要素を予め適切に設計しておかないと、目的に沿ったアクセスや絞り込みができません。検索の柔軟性はSQLに劣ります。

それ以外の属性では検索ができなため、全て取得するScan操作になってしまい、パフォーマンスの劣化に繋がります。
なので、漏れなくアクセスパターンを洗い出したうえで設計しないと、詰んでしまいます。

まとめると下記のようになり、どちらにも大きなメリット・デメリットが存在することを考慮しながら、利用しないといけない。

  • SQLは複雑な条件検索・強力なACID特性を持っているが、新規のカラム(列)を後から追加するのが大変
  • カラムを追加すると宣言してから代入することができるが、既存のシステムもある程度見直す必要性がある
  • NoSQLは柔軟な属性(列)の追加・読み書きの速さを持っているが、色々な属性(列)で検索するのが大変
  • 属性を検索するためにはDynamoDBを例にするとパーティションキー・ソートキー・セカンダリインデックスのみになるため、テーブル設計を怠ると後々パフォーマンスの問題がでてくる

DynamoDBの料金体系

Amazon DynamoDBの料金体系は、主に「使った分だけ支払う」従量課金制で、利用状況に合わせて選べる柔軟な仕組みが特徴です。

課金の仕組み

DynamoDBの料金は、主に以下の3つの要素で決まります。

  • 読み書きの量: データベースへのデータの書き込み(Write)と、データの読み出し(Read)の回数や量に応じて料金が発生します。これが最も主要なコスト要因です。
  • データストレージ量: データベースに保存しているデータ量(GB単位)に応じて、月額のストレージ料金が発生します。
  • その他機能: バックアップ、複数地域へのデータ複製(グローバルテーブル)、データ転送など、追加機能の利用量に応じても料金がかかります。

料金の種類

アプリケーションのアクセスパターンに合わせて、最適なコスト効率を実現できる2種類の料金モデルが用意されています。

1. オンデマンドキャパシティモード

リクエスト量に応じて自動で性能が調整され、実際に処理した読み書きのリクエスト数に対して料金が発生する、完全な従量課金モデルです。

  • 特徴: アクセス量の予測が難しい、または急なスパイクが発生する可能性がある場合に最適です。事前の容量計画が不要で、手軽に始められます。
  • 課金単位: 読み込みリクエスト単位 (RRU) / 書き込みリクエスト単位 (WRU)

2. プロビジョンドキャパシティモード

あらかじめ1秒あたりに必要な読み書きの性能(キャパシティ)を予約し、その確保した性能に対して時間単位で料金を支払うモデルです。

  • 特徴: アクセス量が安定していて予測可能な場合に、オンデマンドよりもコストを抑えられます。
  • 課金単位: 読み込みキャパシティユニット (RCU) / 書き込みキャパシティユニット (WCU)

オートスケーリングと組み合わせることで、「プロビジョンドキャパシティモード」でもアクセス量の増減に合わせて自動で性能を調整し、コストを最適化できます。これにより、安定した性能を維持しつつ、無駄なコストを削減することが可能です。

Serverless FrameworkでDynamoDBをデプロイする手順

それでは、実際にServerless Frameworkを使ってDynamoDBテーブルをAWSにデプロイしてみましょう。

1. 事前準備 (macOS)

まず、以下の準備を済ませておきましょう。
IAMユーザーの作成とAWS CLIの設定: AWSを操作するための認証情報(アクセスキー)を発行し、お使いのPCに設定します。
Serverless Frameworkのインストール: ターミナルで以下のコマンドを実行し、バージョンが表示されればインストール完了です。

% serverless --version

✔ Installed Serverless Framework v4.21.0
Serverless ϟ Framework 4.21.0

Serverless Frameworkへのログイン

初めて使用する場合は、アカウントの作成とログインが必要です。ダッシュボード画面右上の「+Create App」から任意の名前でAppを作成しておきます。
Serverless Framework公式サイト


2. テンプレートからプロジェクトを作成

次に、serverless コマンドを実行して、プロジェクトの雛形を作成します。

% serverless

今回はDynamoDBの設定が予め記述されたテンプレートを選択します。
ターミナルに表示される案内に従って、↑↓キーで項目を選択し、プロジェクトを作成します。

Serverless ϟ Framework

Welcome to Serverless Framework V.4

Create a new project by selecting a Template to generate scaffolding for a specific use-case.

✔ Select A Template: · AWS / Node.js / Express API with DynamoDB
✔ Name Your Project: · testDynamoDB
✔ Template Downloaded
...
Please login/register or enter your license key: · Login/Register
...
✔ You have successfully signed in.
...
✔ Create Or Select An Existing App: · dynamotest # 事前準備で作成したAppを選択

Your new Service "testDynamoDB" is ready. Here are next steps:
• Open Service Directory: cd testDynamoDB
• Install Dependencies: npm install (or use another package manager)
• Deploy Your Service: serverless deploy

コマンドが完了すると、以下のようなディレクトリとファイルが生成されます。

testDynamoDB
├── handler.js
├── package.json
├── README.md
└── serverless.yml

3. serverless.yml の編集

今回はDynamoDBテーブルのデプロイのみが目的のため、設定ファイルである serverless.yml を編集し、Lambdaの実装などの不要な部分を削除します。

# "org" はServerless FrameworkのOrganization名です。
org: your-organization-name # ご自身のOrganization名に書き換えてください
# "app" はServerless Frameworkのダッシュボードで作成したApp名です。
app: your-app-name # ご自身のApp名に書き換えてください
# "service" はこのプロジェクトの名前です。
service: testDynamoDB

stages:
  default:
    params:
      tableName: "test-dynamo-${sls:stage}" # 作成するDynamoDBテーブルの名前

provider:
  name: aws
  runtime: nodejs20.x
  iam:
    role:
      statements:
        - Effect: Allow
          Action: # DynamoDBに対する操作権限を定義
            - dynamodb:Query
            - dynamodb:Scan
            - dynamodb:GetItem
            - dynamodb:PutItem
            - dynamodb:UpdateItem
            - dynamodb:DeleteItem
          Resource:
            - Fn::GetAtt: [UsersTable, Arn]
  environment:
    USERS_TABLE: ${param:tableName}

# ここで実際に作成するAWSリソースを定義します
resources:
  Resources:
    UsersTable:
      Type: AWS::DynamoDB::Table
      Properties:
        AttributeDefinitions:
          - AttributeName: userId # パーティションキー(主キー)の名前
            AttributeType: S # SはString(文字列)を意味します
        KeySchema:
          - AttributeName: userId
          KeyType: HASH # HASHはパーティションキーを意味します
        BillingMode: PAY_PER_REQUEST # 料金体系を従量課金制に設定
        TableName: ${param:tableName}

4. AWSへのデプロイ

serverless.yml ファイルがあるディレクトリに移動し、デプロイコマンドを実行します。

% cd testDynamoDB
% serverless deploy

以下のようなメッセージが表示されれば、デプロイは成功です。

Deploying "testDynamoDB" to stage "dev" (us-east-1)
✔ Service deployed to stack testDynamoDB-dev (30s)

AWSマネジメントコンソールにログインし、DynamoDBのページを開くと、test-dynamo-dev という名前のテーブルが作成されていることを確認できます。

Serverless Frameworkでデプロイすると処理の裏側では、設定したリージョン内でCloudFormationスタックが自動作成され、そこからDynamoDBへとデプロイされています!

今回は実装していませんが、Serverless Frameworkは名前の通り、サーバーレスのサービスデプロイに特化しています。
サーバーレスのサービスの設定を簡潔に記述できるので、AWSのコンソールなどから直接CloudFormationスタックを細かく設定して実行をするよりも、「手軽にAPIGatewayやLambdaを構築したい!」といった時に簡単に実装できるので、迅速な開発が可能です!

5. 削除

料金が発生しても困るので使わないリソースは削除しましょう!

% serverless remove

以下のようなメッセージが表示されれば、削除は成功です。
※念の為、AWSコンソール上でも削除されていることを確認してください。

✔ Installed Serverless Framework v4.21.1

Removing "testDynamoDB" from stage "dev" (us-east-1)

✔ Service testDynamoDB has been successfully removed (22s)

DynamoDBの活用シーン

DynamoDBの柔軟なデータ構造は、活用方法は無数にありますが、一例として挙げるなら以下のような用途など適しています。

  • チャットアプリ: ユーザーごとの会話ログやスレッド情報
  • ゲームデータ: プレイヤーのステータスや所持アイテムなど多様なデータ
  • IoTデバイス: デバイスごとに異なるセンサーデータの保存

さいごに

最後までお読みいただきありがとうございました。Serverless Frameworkを使えば、複雑な設定なしで簡単にDynamoDBを始められます。この記事が、あなたのサーバーレス開発の一助となれば幸いです。ぜひ、実際に手を動かしてNoSQLを体験してみてください!