[AWS CDK] aws_dynamodb.TableV2 Construct クラスを試してみた

グローバルテーブルを使う場合は、特に TableV2 コンストラクトを使うと良さそう
2023.10.08

こんにちは、CX 事業本部 Delivery 部の若槻です。

AWS CDK の aws-cdk-lib » aws_dynamodb モジュールでは、DynamoDB テーブルを作成できる Construct クラスとして、従来の Tableに加え、TableV2 というクラスも提供されています。

両者のドキュメントを見比べると、ほとんど互換性はありそうですが、インデックスやグローバルテーブルの作成方法には違いがあるようです。

今回は、この TableV2 Construct クラスでのテーブル作成を試してみました。

試してみる

実装

aws_dynamodb.TableV2 を使って V2 テーブルを作成してみます。

lib/cdk-sample-stack.ts

import { aws_dynamodb, Stack, StackProps } from 'aws-cdk-lib';
import { Construct } from 'constructs';

export class CdkSampleStack extends Stack {
  constructor(scope: Construct, id: string, props: StackProps) {
    super(scope, id, props);

    // V2 でテーブルを作成
    new aws_dynamodb.TableV2(this, 'TableV2', {
      partitionKey: { name: 'pk', type: aws_dynamodb.AttributeType.STRING },
    });

    // レプリカを指定して V2 でテーブルを作成
    new aws_dynamodb.TableV2(this, 'TableV2WithReplica', {
      partitionKey: { name: 'pk', type: aws_dynamodb.AttributeType.STRING },
      replicas: [{ region: 'us-west-1' }],
    });

    // GSI/LSI を指定して V2 でテーブルを作成
    new aws_dynamodb.TableV2(this, 'TableV2WithIndex', {
      partitionKey: { name: 'pk', type: aws_dynamodb.AttributeType.STRING },
      globalSecondaryIndexes: [
        {
          indexName: 'gsi',
          partitionKey: {
            name: 'group',
            type: aws_dynamodb.AttributeType.STRING,
          },
          projectionType: aws_dynamodb.ProjectionType.INCLUDE,
          nonKeyAttributes: ['name'],
        },
      ],
      localSecondaryIndexes: [], // 略
    });
  }
}

  • replicas を構成することにより、グローバルテーブルのレプリカを作成できます。
  • globalSecondaryIndexes および localSecondaryIndexes を構成することにより、GSI および LSI を作成できます。
    • ただし従来の V1 と同じくインデックス名は指定必須のため、インデックス名を変更せずに nonKeyAttributes の追加などを行うとエラーとなります。

bin/cdk_sample_app.ts

import { App } from 'aws-cdk-lib';
import { CdkSampleStack } from '../lib/cdk-sample-stack';

const app = new App();

new CdkSampleStack(app, 'CdkSampleStack', {
  env: { region: 'ap-northeast-1' },
});

  • グローバルテーブルを作成する場合は、スタックをリージョンに依存させる必要があります。
    • これを指定しない場合は Replica tables are not supported in a region agnostic stack というエラーが発生します。

上記を CDK デプロイしてテーブルを作成します。

TableV2 で作成されたテーブルを確認してみる

dynamodb list-tables コマンドで確認すると、3 つのテーブルが作成されています。

$ aws dynamodb list-tables --query "TableNames[?starts_with(@, 'CdkSampleStack')]"
[
    "CdkSampleStack-TableV26B253703-151T1R1UEG7Y8",
    "CdkSampleStack-TableV2WithIndex84768A43-1NMVU5ABGJ2LO",
    "CdkSampleStack-TableV2WithReplicaE0AACF5B-U7F0YR6IB70O"
]

一方で、CloudFormation 上では AWS::DynamoDB::GlobalTable タイプのテーブルリソースが 3 つ作成されています。レプリカを作成しない場合でも、TableV2 コンストラクトを使用するとグローバルテーブルとして作成されるようです。

TableV1 で作成されたグローバルテーブルを確認してみる

ここで、比較のために、Table コンストラクトでグローバルテーブルを作成してみます。

lib/cdk-sample-stack.ts

    // 比較のため、レプリカを指定して V1 テーブルを作成
    new aws_dynamodb.Table(this, 'Table', {
      partitionKey: { name: 'pk', type: aws_dynamodb.AttributeType.STRING },
      replicationRegions: ['us-west-1'],
    });

すると、同じグローバルテーブルの作成でも、カスタムリソースを使ってレプリカが作成されていることが分かります。V2 と比べて作成に時間も要しました。リソースタイプは AWS::DynamoDB::Table です。

まとめ:グローバルテーブルを使う場合は TableV2 コンストラクトを使うと良さそう

ここで、ドキュメントによると、グローバルテーブルには Version 2019.11.21Version 2017.11.29 の 2 つがあり、AWS::DynamoDB::GlobalTable は新しい方のタイプとのことです。

The AWS::DynamoDB::GlobalTable resource enables you to create and manage a Version 2019.11.21 global table. This resource cannot be used to create or manage a Version 2017.11.29 global table. For more information, see Global tables.

Important
You cannot convert a resource of type AWS::DynamoDB::Table into a resource of type AWS::DynamoDB::GlobalTable by changing its type in your template. Doing so might result in the deletion of your DynamoDB table.

You can instead use the GlobalTable resource to create a new table in a single Region. This will be billed the same as a single Region table. If you later update the stack to add other Regions then Global Tables pricing will apply.

You should be aware of the following behaviors when working with DynamoDB global tables.

そしてもしテーブルのリソースタイプを AWS::DynamoDB::Table から AWS::DynamoDB::GlobalTable にリソースタイプを変更した場合はテーブル削除が発生する可能性があるため、AWS::DynamoDB::GlobalTable を単一リージョンに作成して、後から他のリージョンを追加するようにあります。

よって、グローバルテーブルを利用する、または利用する可能性があるのであれば、新しいリソースタイプで効率的にリソースの管理が行えるので TableV2 コンストラクトを使うべきだと思います。

またそうでなくとも、今後すぐに従来の Table コンストラクトが Deprecated になることは無いと思いますが、TableV2 への移行は見込まれると思うので、今後新規作成するテーブルでは TableV2 コンストラクトを採用しても良いのでは無いでしょうか。

以上