見出し画像

DynamoDBのlib-dynamodbのライブラリでバッチ書き込み処理をしてみた

こんにちは、buildサービス部の鈴木です。
新年の2024年になりましたね。今年は夏が暑かったのを引きずってか、冬が例年より暖かいですね。とはいえ依然としてコロナやインフルエンザが流行しているみたいですので皆さんくれぐれも体調管理には気をつけてください。

さて、今回は現在開発で使用しているDynamoDBにおいて書き込み処理のバッチ処理をAWSから提供されているlib-dynamodbを用いて行ったのでそれについて話したいと思います。

DynamoDBの書き込み処理について

通常では、PutCommand (挿入),UpdateCommand(更新),DeleteCommand(削除)の3つを使うことで引数として指定したレコードを書き込み操作することができます。
処理を書いてく上で、複数のレコードの操作を一括でしたい場合は通常であればfor文を回してレコードの書き込みを繰り返す、といった実装方法が考えられますが、その一連の処理の途中でもしエラーが生じた場合は、一部の成功した処理も書き込み前の状態に戻したい、要するにトランザクション処理をしたいといったことがあるかと思います。
AWS側もそのニーズは把握しており、それにあわせてライブラリにそのための関数であるTransactWriteItemsBatchWriteItemsを用意しています。

lib-dyanmodbがサポートしているバッチ書き込み処理

lib-dynamodbはバッチ処理としてTransactWriteCommandBatchWriteCommandを用意しています。
どちらも似たような関数であり、複数のテーブルに対してまとめての書き込みを処理の管理を行なってくれますが名前が違う通り機能にも差異があります。

TransactWriteCommand

  • 一度のリクエストで最大 100 個の項目の挿入、更新、削除操作可能

  • 処理途中でエラーとなった場合、全てのレコードが処理前の状態に戻る

  • リクエストに条件確認(ConditionCheck)を指定することができる

  • 一つの書き込みのコストが2倍かかる

  • 幂等なリクエストを許可する(10分以内)。

  • トランザクション内のアイテムの合計サイズは 4 MB を超えることはできない

const transactCommandInput: TransactWriteCommandInput = {
        TransactItems: [
            {
                Put: {
                    TableName: "tableName",
                    Item: {
                        partitionKey: 'partitionKey',
                        role: "role_admin",
                    },
                    ConditionExpression: "attribute_not_exists (partitionKey)",
                },
            },
            {
                Update: {
                    TableName: "tableName",
                    Key: {
                        partitionKey: 'partitionKey',
                    },
                    UpdateExpression: "set role = :role",
                    ExpressionAttributeValues: {
                        ":role": "role_normal",
                    },
                },
            },
            {
                Delete: {
                    TableName: "tableName",
                    Key: {
                        partitionKey: 'partitionKey',
                    },
                },
            },
        ],
    }

BatchWriteCommand

  • 一度のリクエストで最大 25 個の項目の挿入、削除操作が可能
    一方で、更新操作(UpdateCommand)は不可能。ただし、既存項目と合致するキーのPutCommandを行うことでレコードの更新が可能

  • 処理途中でエラーとなった場合、失敗した項目はUnprocessedItemsとして返却される

  • リクエストに条件確認(ConditionCheck)を指定することができない

  • 書き込みコストが少ない分、処理時間は短い

  • リクエストのアイテムの合計サイズは 16 MB を超えることはできない

const batchCommandInput: BatchWriteCommandInput = {
  RequestItems: {
    [this.config.tableName]: [
      {
        PutRequest: {
          Item: {
            partitionKey: 'partitionKey',
            sortKey: 'sortkey',
            status: `${Params.status}`,
            userId: params.userId
          }
        }
      },
      {
        DeleteRequest: {
          Key: {
            partitionKey: 'partitionKey',
            sortKey: 'sortkey'
          }
        }
      }
    ]
  }
};

こういった違いがありますので、状況に応じて使い分けましょう。