複数の Amazon DynamoDB テーブルのキャパシティモードを同時に変更する方法を教えてください。
複数の Amazon DynamoDB テーブルのキャパシティモードを同時に変更したいです。
簡単な説明
複数の DynamoDB テーブルのキャパシティモードを変更する場合、プロビジョンドキャパシティモードまたはオンデマンドキャパシティモードのいずれかを指定する必要があります。キャパシティモードを変更する前に、「DynamoDB でキャパシティモードを切り替える際の考慮事項」を参照してください。
複数の DynamoDB テーブルのキャパシティモードを同時に変更するには、次のいずれかの方法を使用します。
- AWS コマンドラインインターフェイス (AWS CLI)
- AWS CloudFormation
- Python
解決策
ベストプラクティス
複数の DynamoDB テーブルのキャパシティモードを変更する際は、次のベストプラクティスを実施してください。
- 変更を開始する前に、適切な AWS CLI 認証情報を設定します。
- 適切な AWS Identity and Access Management (IAM) アクセス許可があることを確認してください。
- まず、変更を非実稼働環境にデプロイします。
- 各テーブルで切り替えが完了するまで数分かかります。
- キャパシティモードは、各テーブルで 24 時間に 1 回のみ切り替えます。
- 使用パターンを分析して適切なキャパシティモードを選択し、AWS リージョンの要件に合わせて調整します。
- 切り替え後のコストを監視して、適切なキャパシティがプロビジョニングされていることを確認します。
AWS CLI
注: AWS コマンドラインインターフェイス (AWS CLI) コマンドの実行中にエラーが発生した場合は、「AWS CLI で発生したエラーのトラブルシューティング」を参照してください。また、AWS CLI の最新バージョンを使用していることを確認してください。
プロビジョンドモード
AWS CLI を使用して複数の DynamoDB テーブルのキャパシティモードをプロビジョンドモードに変更するには、次の手順を実行します。
-
テキストエディタを開き、次のコードを入力して新しいシェルスクリプトを作成します。
#!/bin/bash # Set the AWS region AWS_REGION=[REGION] # Change this to your desired region # OPTION1: List of table names you want to switch TABLES=("table1" "table2" "table3") # OPTION2: Get all table names in the account TABLES=$(aws dynamodb list-tables —region $AWS_REGION —query 'TableNames[]' —output text) # Default provisioned capacity units READ_CAPACITY=READ_CAPACITY_VALUE WRITE_CAPACITY=WRITE_CAPACITY_VALUE echo "Using AWS Region: $AWS_REGION" for TABLE_NAME in $TABLES do # Check current billing mode CURRENT_MODE=$(aws dynamodb describe-table —region $AWS_REGION —table-name $TABLE_NAME —query 'Table.BillingModeSummary.BillingMode' —output text) if [ "$CURRENT_MODE" = "PAY_PER_REQUEST" ]; then echo "Processing table: $TABLE_NAME" # Get GSI configurations GSI_CONFIG="" GSI_LIST=$(aws dynamodb describe-table —region $AWS_REGION —table-name $TABLE_NAME —query 'Table.GlobalSecondaryIndexes[*].IndexName' —output text) if [ ! -z "$GSI_LIST" ]; then echo "Found GSIs: $GSI_LIST" # Build GSI provisioned throughput configuration GSI_CONFIG="—global-secondary-index-updates“ for GSI_NAME in $GSI_LIST do if [ -z "$FIRST_GSI" ]; then GSI_CONFIG="$GSI_CONFIG [{\"Update\":{\"IndexName\":\"$GSI_NAME\",\"ProvisionedThroughput\":{\"ReadCapacityUnits\":$READ_CAPACITY,\"WriteCapacityUnits\":$WRITE_CAPACITY}}}" FIRST_GSI="false" else GSI_CONFIG="$GSI_CONFIG,{\"Update\":{\"IndexName\":\"$GSI_NAME\",\"ProvisionedThroughput\":{\"ReadCapacityUnits\":$READ_CAPACITY,\"WriteCapacityUnits\":$WRITE_CAPACITY}}}" fi done GSI_CONFIG="$GSI_CONFIG]" fi # Update table and GSIs if [ ! -z "$GSI_CONFIG" ]; then echo "Updating table and GSIs..." aws dynamodb update-table \ --region $AWS_REGION \ --table-name $TABLE_NAME \ --billing-mode PROVISIONED \ --provisioned-throughput ReadCapacityUnits=$READ_CAPACITY,WriteCapacityUnits=$WRITE_CAPACITY \ $GSI_CONFIG else echo "Updating table (no GSIs)..." aws dynamodb update-table \ --region $AWS_REGION \ --table-name $TABLE_NAME \ --billing-mode PROVISIONED \ --provisioned-throughput ReadCapacityUnits=$READ_CAPACITY,WriteCapacityUnits=$WRITE_CAPACITY fi echo "Request submitted for $TABLE_NAME" else echo "Skipping $TABLE_NAME - already in PROVISIONED mode" fi # Reset GSI tracking for next table FIRST_GSI="" echo "----------------------------------------" doneすべての DynamoDB テーブルのキャパシティモードをオンデマンドモードに変更するには、コードから次のセクションを削除します。
#OPTION1: List of table names you want to switch TABLES=("table1" "table2" "table3")特定の複数 DynamoDB テーブルのキャパシティモードをオンデマンドモードに変更するには、"table1" "table2" "table3" を該当するテーブル名に置き換えます。次に、コードから以下のセクションを削除します。
#OPTION2: Get all table names in the account TABLES=$(aws dynamodb list-tables —query 'TableNames[]' —output text)注: READ_CAPACITY_VALUE および WRITE_CAPACITY_VALUE を実際の読み取りおよび書き取りキャパシティ値に置き換えます。
-
このファイルを switch-all-tables-with-gsi-to-provisioned.sh という名前で保存します。
-
ファイルを実行可能にするには、ターミナルを開いて次のコマンドを実行します。
chmod +x switch-all-tables-with-gsi-to-provisioned.sh -
ターミナルでシェルスクリプトを実行するには、次のコマンドを実行します。
./switch-all-tables-with-gsi-to-provisioned.sh
オンデマンドモード
AWS CLI を使用して複数の DynamoDB テーブルのキャパシティモードをオンデマンドモードに変更するには、次の手順を実行します。
-
テキストエディタを開き、次のコードを入力して新しいシェルスクリプトを作成します。
#!/bin/bash # Set the AWS region AWS_REGION=[REGION] # Change this to your desired region # OPTION1: List of table names you want to switch TABLES=("table1" "table2" "table3") # OPTION2: Get all table names in the account #TABLES=$(aws dynamodb list-tables --region $AWS_REGION --query 'TableNames[]' --output text) for TABLE_NAME in $TABLES do # Check current billing mode CURRENT_MODE=$(aws dynamodb describe-table --region $AWS_REGION --table-name $TABLE_NAME --query 'Table.BillingModeSummary.BillingMode' --output text) if [ "$CURRENT_MODE" = "PROVISIONED" ]; then echo "Processing table: $TABLE_NAME" # Check if table has any GSIs GSI_LIST=$(aws dynamodb describe-table --region $AWS_REGION --table-name $TABLE_NAME --query 'Table.GlobalSecondaryIndexes[*].IndexName' --output text) if [ ! -z "$GSI_LIST" ]; then echo "Table has GSIs: $GSI_LIST" echo "Note: GSIs will automatically switch to On-Demand with the table" fi # Update table to On-Demand echo "Switching $TABLE_NAME to PAY_PER_REQUEST mode..." aws dynamodb update-table \ --region $AWS_REGION \ --table-name $TABLE_NAME \ --billing-mode PAY_PER_REQUEST echo "Request submitted for $TABLE_NAME" else echo "Skipping $TABLE_NAME - already in PAY_PER_REQUEST mode" fi echo "----------------------------------------" doneすべての DynamoDB テーブルのキャパシティモードをオンデマンドモードに変更するには、コードから次のセクションを削除します。
#OPTION1: List of table names you want to switch TABLES=("table1" "table2" "table3")特定の複数 DynamoDB テーブルのキャパシティモードをオンデマンドモードに変更するには、"table1" "table2" "table3" を該当するテーブル名に置き換えます。次に、コードから以下のセクションを削除します。
`#OPTION2: Get all table names in the account` TABLES=$(aws dynamodb list-tables —region $AWS\_REGION —query 'TableNames\[\]' —output text)注: REGION を実際のリージョンに置き換えます。リージョンコードを使用します (例: us-east-1)。
-
ファイルを実行可能にするには、ターミナルを開いてコマンドを実行します。
chmod +x switch-all-tables-with-gsi-to-ondemand.sh -
ターミナルでシェルスクリプトを実行するには、次のコマンドを実行します。
./switch-all-tables-with-gsi-to-ondemand.sh
CloudFormation
次のベストプラクティスを実施します。
- Python 3.9 ランタイムを使用するように AWS Lambda テンプレートを設定します。
- Amazon CloudWatch Logs を監視して Lambda 関数の進行状況を追跡します。
注: 開始する前に、AWS 認証情報を設定します。次の AWS CLI コマンド configure を実行します。
aws configure
プロビジョンドモード
CloudFormation を使用して複数の DynamoDB テーブルのキャパシティモードをプロビジョンドモードに変更するには、次の手順を実行します。
-
テキストエディタを開き、次のコードを入力して新しい YAML ファイルを作成します。
AWSTemplateFormatVersion: '2010-09-09' Description: 'Switch specific DynamoDB tables from On-Demand to Provisioned capacity mode' Parameters: ReadCapacityUnits: Type: Number Default: 5 Description: Read Capacity Units for tables and GSIs WriteCapacityUnits: Type: Number Default: 5 Description: Write Capacity Units for tables and GSIs TableNames: Type: CommaDelimitedList Description: Comma-separated list of DynamoDB table names to update Resources: DynamoDBTableUpdates: Type: Custom::DynamoDBTableUpdates Properties: ServiceToken: !GetAtt UpdateTablesFunction.Arn ReadCapacityUnits: !Ref ReadCapacityUnits WriteCapacityUnits: !Ref WriteCapacityUnits TableNames: !Ref TableNames UpdateTablesFunction: Type: AWS::Lambda::Function Properties: Runtime: python3.9 Handler: index.handler Role: !GetAtt LambdaExecutionRole.Arn Code: ZipFile: | import boto3 import cfnresponse def handler(event, context): try: if event['RequestType'] in ['Create', 'Update']: dynamodb = boto3.client('dynamodb') # Get parameters read_capacity = event['ResourceProperties']['ReadCapacityUnits'] write_capacity = event['ResourceProperties']['WriteCapacityUnits'] table_names = event['ResourceProperties']['TableNames'] for table_name in table_names: try: # Get table details table = dynamodb.describe_table(TableName=table_name)['Table'] current_mode = table.get('BillingModeSummary', {}).get('BillingMode', '') if current_mode == 'PAY_PER_REQUEST': # Prepare GSI updates if any gsi_updates = [] if 'GlobalSecondaryIndexes' in table: for gsi in table['GlobalSecondaryIndexes']: gsi_updates.append({ 'Update': { 'IndexName': gsi['IndexName'], 'ProvisionedThroughput': { 'ReadCapacityUnits': int(read_capacity), 'WriteCapacityUnits': int(write_capacity) } } }) # Update table update_params = { 'TableName': table_name, 'BillingMode': 'PROVISIONED', 'ProvisionedThroughput': { 'ReadCapacityUnits': int(read_capacity), 'WriteCapacityUnits': int(write_capacity) } } if gsi_updates: update_params['GlobalSecondaryIndexUpdates'] = gsi_updates dynamodb.update_table(**update_params) print(f"Switching {table_name} to PROVISIONED mode") else: print(f"Table {table_name} is not in PAY_PER_REQUEST mode. Skipping.") except Exception as e: print(f"Error processing table {table_name}: {str(e)}") continue cfnresponse.send(event, context, cfnresponse.SUCCESS, {}) else: cfnresponse.send(event, context, cfnresponse.SUCCESS, {}) except Exception as e: print(f"Error: {str(e)}") cfnresponse.send(event, context, cfnresponse.FAILED, {}) LambdaExecutionRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: lambda.amazonaws.com Action: sts:AssumeRole ManagedPolicyArns: - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole Policies: - PolicyName: DynamoDBAccess PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: - dynamodb:DescribeTable - dynamodb:UpdateTable Resource: '*' -
このファイルを switch-to-provisioned.yaml という名前で保存します。
-
次の AWS CLI コマンド create-stack を実行します。
# For Provisioned mode aws cloudformation create-stack \ --stack-name switch-to-provisioned \ --template-body file://switch-to-provisioned.yaml \ --capabilities CAPABILITY_IAM \ --region [REGION] \ --parameters ParameterKey=TableNames,ParameterValue="Table1,Table2,Table3" \ ParameterKey=ReadCapacityUnits,ParameterValue=[RCU_VALUE] \ ParameterKey=WriteCapacityUnits,ParameterValue=[WCU_VALUE]注: 実際のものでそれぞれ、"Table1,Table2,Table3" をテーブル名に、RCU_VALUE および WCU_VALUE を RCU と WCU 値に、REGION をリージョン (例: us-east-1) に置き換えます。
オンデマンドモード
CloudFormation を使用して複数の DynamoDB テーブルのキャパシティモードをオンデマンドモードに変更するには、次の手順を実行します。
-
テキストエディタを開き、次のコードを入力して新しい YAML ファイルを作成します。
AWSTemplateFormatVersion: '2010-09-09' Description: 'Switch specific DynamoDB tables from Provisioned to On-Demand capacity mode' Parameters: TableNames: Type: CommaDelimitedList Description: Comma-separated list of DynamoDB table names to update Resources: DynamoDBTableUpdates: Type: Custom::DynamoDBTableUpdates Properties: ServiceToken: !GetAtt UpdateTablesFunction.Arn TableNames: !Ref TableNames UpdateTablesFunction: Type: AWS::Lambda::Function Properties: Runtime: python3.9 Handler: index.handler Role: !GetAtt LambdaExecutionRole.Arn Code: ZipFile: | import boto3 import cfnresponse def handler(event, context): try: if event['RequestType'] in ['Create', 'Update']: dynamodb = boto3.client('dynamodb') # Get table names from the event table_names = event['ResourceProperties']['TableNames'] for table_name in table_names: try: # Get table details table = dynamodb.describe_table(TableName=table_name)['Table'] current_mode = table.get('BillingModeSummary', {}).get('BillingMode', '') if current_mode == 'PROVISIONED': # Update table to On-Demand dynamodb.update_table( TableName=table_name, BillingMode='PAY_PER_REQUEST' ) print(f"Switching {table_name} to PAY_PER_REQUEST mode") else: print(f"Table {table_name} is not in PROVISIONED mode. Skipping.") except Exception as e: print(f"Error processing table {table_name}: {str(e)}") continue cfnresponse.send(event, context, cfnresponse.SUCCESS, {}) else: cfnresponse.send(event, context, cfnresponse.SUCCESS, {}) except Exception as e: print(f"Error: {str(e)}") cfnresponse.send(event, context, cfnresponse.FAILED, {}) LambdaExecutionRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: lambda.amazonaws.com Action: sts:AssumeRole ManagedPolicyArns: - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole Policies: - PolicyName: DynamoDBAccess PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: - dynamodb:DescribeTable - dynamodb:UpdateTable Resource: '*' -
このファイルを switch-to-ondemand.yaml という名前で保存します。
-
次の AWS CLI コマンド create-stack を実行します。
# For On-Demand mode aws cloudformation create-stack \ --stack-name switch-to-ondemand \ --template-body file://switch-to-ondemand.yaml \ --capabilities CAPABILITY_IAM \ --region [REGION] \ --parameters ParameterKey=TableNames,ParameterValue="Table1,Table2,Table3"注: 実際のものでそれぞれ、"Table1,Table2,Table3" をテーブル名に、REGION をリージョンに置き換えます。
Python
Python スクリプトの実行には、Amazon Elastic Compute Cloud (EC2) インスタンス、Lambda、または独自のデスクトップを使用できます。キャパシティモードを変更する前に、Python、pip、boto3 がインストールされていることを確認してください。
開始する前に、AWS 認証情報を設定します。次の AWS CLI コマンド configure を実行します。
aws configure
プロビジョンドモード
Python スクリプトを使用して、特定のリージョンのすべての DynamoDB テーブルのキャパシティモードをプロビジョンドモードに変更するには、次の手順を実行します。
-
Python を開き、次のコードを入力して新しいファイルを作成します。
import boto3 import time from botocore.exceptions import ClientError def switch_to_provisioned(read_capacity=5, write_capacity=5, region=None): """ Switch all DynamoDB tables from On-Demand to Provisioned capacity mode """ # Initialize DynamoDB client dynamodb = boto3.client('dynamodb', region_name=region) # Get all table names tables = [] paginator = dynamodb.get_paginator('list_tables') for page in paginator.paginate(): tables.extend(page['TableNames']) print(f"Found {len(tables)} tables") for table_name in tables: try: # Get table details response = dynamodb.describe_table(TableName=table_name) table = response['Table'] current_mode = table.get('BillingModeSummary', {}).get('BillingMode', '') if current_mode == 'PAY_PER_REQUEST': print(f"\nProcessing table: {table_name}") # Prepare GSI updates if any gsi_updates = [] if 'GlobalSecondaryIndexes' in table: print(f"Found GSIs for table {table_name}") for gsi in table['GlobalSecondaryIndexes']: gsi_updates.append({ 'Update': { 'IndexName': gsi['IndexName'], 'ProvisionedThroughput': { 'ReadCapacityUnits': read_capacity, 'WriteCapacityUnits': write_capacity } } }) # Prepare update parameters update_params = { 'TableName': table_name, 'BillingMode': 'PROVISIONED', 'ProvisionedThroughput': { 'ReadCapacityUnits': read_capacity, 'WriteCapacityUnits': write_capacity } } if gsi_updates: update_params['GlobalSecondaryIndexUpdates'] = gsi_updates # Update table print(f"Switching {table_name} to PROVISIONED mode...") dynamodb.update_table(**update_params) print(f"Update request submitted for {table_name}") else: print(f"\nSkipping {table_name} - already in PROVISIONED mode") except ClientError as e: if e.response['Error']['Code'] == 'LimitExceededException': print(f"\nError: Cannot update {table_name}. You can only switch between billing modes once per 24 hours.") else: print(f"\nError processing table {table_name}: {str(e)}") continue except Exception as e: print(f"\nUnexpected error processing table {table_name}: {str(e)}") continue # Small delay to avoid API throttling time.sleep(1) if __name__ == "__main__": # You can modify these values READ_CAPACITY = [RCU_VALUE] WRITE_CAPACITY = [WCU_VALUE] REGION = [REGION] # Change to your desired region switch_to_provisioned( read_capacity=READ_CAPACITY, write_capacity=WRITE_CAPACITY, region=REGION )注: 実際のものでそれぞれ、RCU_VALUE および WCU_VALUE を RCU と WCU 値に、REGION をリージョン (例: us-east-1) に置き換えます。
-
ファイルを switch_to_provisioned.py という名前で保存します。
-
ターミナルを開き、次のコマンドを実行して Python スクリプトを実行します。
python switch_to_provisioned.py
オンデマンドモード
Python スクリプトを使用して、特定のリージョンのすべての DynamoDB テーブルのキャパシティモードをオンデマンドモードに変更するには、次の手順を実行します。
-
Python を開き、次のコードを入力して新しいファイルを作成します。
import boto3 import time from botocore.exceptions import ClientError def switch_to_ondemand(region=None): """ Switch all DynamoDB tables from Provisioned to On-Demand capacity mode """ # Initialize DynamoDB client dynamodb = boto3.client('dynamodb', region_name=region) # Get all table names tables = [] paginator = dynamodb.get_paginator('list_tables') for page in paginator.paginate(): tables.extend(page['TableNames']) print(f"Found {len(tables)} tables") for table_name in tables: try: # Get table details response = dynamodb.describe_table(TableName=table_name) table = response['Table'] current_mode = table.get('BillingModeSummary', {}).get('BillingMode', '') if current_mode == 'PROVISIONED': print(f"\nProcessing table: {table_name}") # Check for GSIs if 'GlobalSecondaryIndexes' in table: print(f"Table {table_name} has GSIs - they will automatically switch to On-Demand") # Update table print(f"Switching {table_name} to PAY_PER_REQUEST mode...") dynamodb.update_table( TableName=table_name, BillingMode='PAY_PER_REQUEST' ) print(f"Update request submitted for {table_name}") else: print(f"\nSkipping {table_name} - already in PAY_PER_REQUEST mode") except ClientError as e: if e.response['Error']['Code'] == 'LimitExceededException': print(f"\nError: Cannot update {table_name}. You can only switch between billing modes once per 24 hours.") else: print(f"\nError processing table {table_name}: {str(e)}") continue except Exception as e: print(f"\nUnexpected error processing table {table_name}: {str(e)}") continue # Small delay to avoid API throttling time.sleep(1) def check_table_status(table_name, region=None): """ Check the current billing mode of a specific table """ dynamodb = boto3.client('dynamodb', region_name=region) try: response = dynamodb.describe_table(TableName=table_name) mode = response['Table'].get('BillingModeSummary', {}).get('BillingMode', 'Unknown') print(f"Table {table_name} is in {mode} mode") return mode except Exception as e: print(f"Error checking table {table_name}: {str(e)}") return None if __name__ == "__main__": REGION = [REGION] # Change to your desired region switch_to_ondemand(region=REGION)注: REGION を実際のリージョンに置き換えます。
-
このファイルを switch_to_ondemand.py という名前で保存します。
-
ターミナルを開き、次のコマンドを実行して Python スクリプトを実行します。
python switch_to_ondemand.py
