Closed9

DynamoDBはLSI変更の夢を見るか?

innosshinnossh

既存のDynamoDBテーブルのLocal Secondary Indexesを変更することはできるのか

innosshinnossh

LSIのドキュメントを確認する。

https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LSI.html#LSI.Creating

To create one or more local secondary indexes on a table, use the LocalSecondaryIndexes parameter of the CreateTable operation. Local secondary indexes on a table are created when the table is created. When you delete a table, any local secondary indexes on that table are also deleted.

LSIはテーブル作成時しか作成できませんよ、と。

innosshinnossh

つまり、LSIを変更したい時、新規のテーブルとして再作成するしかない。
そして既存のテーブルのデータを保持したい場合には、再作成したテーブルへのデータ移行が必要になる。
データ移行には以下の方法が考えられる。

  • テーブルのバックアップを作成し、リストアをする
  • データをS3にエクスポートし、インポートする
innosshinnossh

まず前者のバックアップを使用したリストアによるデータ移行。ドキュメントを確認する。
https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Restore.Tutorial.html

コンソールのキャプチャにもあるように

リストア時に

  • Restore the entire table
  • Restore the table without secondary indexes

を選択できるが、これは全インデックスをリストアする or 全インデックスをリストアしない の選択なので、バックアップ元のLSIがリストアされるだけであり、LSIの変更ができるわけではない。

innosshinnossh

ちなみにAWS BackupではなくDynamoDBのpoint-in-time recovery (PITR)でのバックアップであっても同様にLSIの変更はできない。

https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/PointInTimeRecovery_Howitworks.html

You restore a table without consuming any provisioned throughput on the table. You can do a full table restore using point-in-time recovery, or you can configure the destination table settings. You can change the following table settings on the restored table:

  • Global secondary indexes (GSIs)
  • Local secondary indexes (LSIs)
  • Billing mode
  • Provisioned read and write capacity
  • Encryption settings

ドキュメントでは変更できるっぽい雰囲気で書いてあるが、同上でLSIの変更ができるわけではない。

innosshinnossh

続いて後者のデータのエクスポート、インポートによるデータ移行。ドキュメントはこちら。

https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/S3forDynamoDB.html

https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/S3DataExport_Requesting.html

https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/S3DataImport.Requesting.html

S3へのインポート、エクスポートは便利である。
しかし、インポートは新規のテーブルにしか実行できない。
更に、インポート時の新規テーブル作成ではLSIを作成することができない。なお、GSIは自由に追加作成できる。
つまり、この方法でもLSIの変更はできないということ。

re:Postにも書いている人がいた。
https://repost.aws/questions/QUHtCwkvOzRDaYdIq7TKbrLA/dynamodb-import-from-s3-does-not-support-localsecondaryindexes-bug-or-intended-behaviour

innosshinnossh

で、結局LSIを変更したい場合はどうするのって話だけど簡単な方法は無さそうに見えた。
おそらく以下の3択になる。

  • データ保持を諦めて、テーブルの再作成
    • 開発段階での最終手段
  • LSIの変更を諦めて、GSIで目的のインデックスを作成する
    • アプリケーション側の利用インデックスの変更が必要になるが、まあ受け入れられるかも
  • 自前で頑張ってデータ移行をする

もし自前のDataPipelineの方法がうまく動くのなら、後発のS3インポート機能でも既存のテーブルを指定できるようにして欲しかった。

innosshinnossh

結論として、どうしてもLSIを変更しつつデータを保持したい場合の現時点での最善策は以下となる。

  1. 対象のDynamoDBテーブルに対してS3エクスポートを実行する
  2. 期待するLSIを持った新規DynamoDBテーブルを作成する
  3. スクリプトなどを実装し、S3上のデータを読んで、作成したテーブルにBatchWriteItemなどでデータ移行をする

ノーコードでは無理そう。
以上。

このスクラップは5ヶ月前にクローズされました