Dynamodb-quick-guide

提供:Dev Guides
移動先:案内検索

DynamoDB-概要

DynamoDBを使用すると、ユーザーは任意の量のデータを保存および取得し、任意の量のトラフィックを処理できるデータベースを作成できます。 各顧客の要求を動的に管理するためにサーバーにデータとトラフィックを自動的に分散し、高速なパフォーマンスも維持します。

DynamoDB対 RDBMS

DynamoDBはNoSQLモデルを使用します。つまり、非リレーショナルシステムを使用します。 次の表は、DynamoDBとRDBMSの違いを強調しています-

Common Tasks RDBMS DynamoDB
Connect to the Source It uses a persistent connection and SQL commands. It uses HTTP requests and API operations
Create a Table Its fundamental structures are tables, and must be defined. It only uses primary keys, and no schema on creation. It uses various data sources.
Get Table Info All table info remains accessible Only primary keys are revealed.
Load Table Data It uses rows made of columns. In tables, it uses items made of attributes
Read Table Data It uses SELECT statements and filtering statements. It uses GetItem, Query, and Scan.
Manage Indexes It uses standard indexes created through SQL statements. Modifications to it occur automatically on table changes. It uses a secondary index to achieve the same function. It requires specifications (partition key and sort key).
Modify Table Data It uses an UPDATE statement. It uses an UpdateItem operation.
Delete Table Data It uses a DELETE statement. It uses a DeleteItem operation.
Delete a Table It uses a DROP TABLE statement. It uses a DeleteTable operation.

利点

DynamoDBの2つの主な利点は、スケーラビリティと柔軟性です。 特定のデータソースと構造の使用を強制することはなく、ユーザーは事実上あらゆるものを操作できますが、統一された方法で操作できます。

また、その設計は、より軽いタスクや操作から要求の厳しいエンタープライズ機能に至るまで、幅広い使用をサポートしています。 また、Ruby、Java、Python、C#、Erlang、PHP、Perlなどの複数の言語を簡単に使用できます。

制限事項

DynamoDBには特定の制限がありますが、これらの制限は必ずしも大きな問題を生み出したり、堅実な開発を妨げるものではありません。

あなたは次の点からそれらを確認することができます-

  • 容量単位サイズ-読み取り容量単位は、4KB以下のアイテムの1秒あたりの単一の一貫した読み取りです。 書き込みキャパシティーユニットは、1KB以下のアイテムに対する1秒あたり1回の書き込みです。
  • プロビジョニングされたスループットの最小/最大-すべてのテーブルとグローバルセカンダリインデックスには、少なくとも1つの読み取りキャパシティーユニットと1つの書き込みキャパシティーユニットがあります。 最大値は地域によって異なります。 米国では、テーブルごとに40Kの読み取りと書き込みの上限(アカウントごとに80K)が残り、他の地域ではテーブルごとに10Kの上限があり、アカウントの上限は20Kです。
  • プロビジョニングされたスループットの増加と減少-これは必要に応じて何度でも増加できますが、減少はテーブルごとに1日4回までに制限されています。
  • 表のサイズとアカウントごとの数量-表のサイズに制限はありませんが、より高い上限を要求しない限り、アカウントには256の表の制限があります。
  • テーブルごとのセカンダリインデックス-5つのローカルおよび5つのグローバルが許可されています。
  • テーブルごとのセカンダリインデックス属性の予測-DynamoDBでは20の属性を使用できます。
  • パーティションキーの長さと値-最小長は1バイト、最大長は2048バイトですが、DynamoDBは値に制限を設けていません。
  • キーの長さと値の並べ替え-テーブルのローカルセカンダリインデックスを使用しない限り、最小長は1バイト、最大長は1024バイトです。値に制限はありません。
  • テーブルおよびセカンダリインデックス名-名前は​​、長さが最低3文字、最高255文字に準拠する必要があります。 A〜Z、a〜z、0〜9、「_」、「-」、「。」の文字を使用します。
  • 属性名-キーと特定の属性を除き、1文字が最小のまま、最大64KBが残ります。
  • 予約語-DynamoDBは予約語を名前として使用することを妨げません。
  • Expression Length -式の文字列には4KBの制限があります。 属性式には255バイトの制限があります。 式の置換変数には2MBの制限があります。

DynamoDB-基本概念

DynamoDBを使用する前に、その基本的なコンポーネントとエコシステムに精通する必要があります。 DynamoDBエコシステムでは、テーブル、属性、アイテムを操作します。 テーブルにはアイテムのセットが保持され、アイテムには属性のセットが保持されます。 属性は、さらに分解する必要のないデータの基本要素、つまりフィールドです。

主キー

主キーはテーブルアイテムを一意に識別する手段として機能し、セカンダリインデックスはクエリの柔軟性を提供します。 DynamoDBストリームは、テーブルデータを変更することにより、レコードイベントをストリーミングします。

テーブルの作成では、名前を設定するだけでなく、主キーも設定する必要があります。テーブル項目を識別します。 キーを共有するアイテムは2つありません。 DynamoDBは2種類の主キーを使用します-

  • パーティションキー-この単純なプライマリキーは、「パーティションキー」と呼ばれる単一の属性で構成されます。内部的に、DynamoDBはハッシュ値の入力としてキー値を使用してストレージを決定します。
  • パーティションキーとソートキー-このキーは「複合プライマリキー」と呼ばれ、2つの属性で構成されています。
  • パーティションキーと
  • ソートキー。 + DynamoDBは最初の属性をハッシュ関数に適用し、同じパーティションキーを持つアイテムを一緒に保存します。ソートキーによって順序が決定されます。 アイテムはパーティションキーを共有できますが、ソートキーは共有できません。

主キー属性では、スカラー(単一)値のみが許可されます。文字列、数値、またはバイナリのデータ型。 非キー属性にはこれらの制約はありません。

二次インデックス

これらのインデックスにより、代替キーを使用してテーブルデータをクエリできます。 DynamoDBは使用を強制しませんが、クエリを最適化します。

DynamoDBは2種類のセカンダリインデックスを使用します-

  • グローバルセカンダリインデックス-このインデックスにはパーティションキーとソートキーがあり、テーブルキーとは異なる場合があります。
  • ローカルセカンダリインデックス-このインデックスはテーブルと同じパーティションキーを持っていますが、ソートキーは異なります。

API

DynamoDBが提供するAPI操作には、コントロールプレーン、データプレーン(作成、読み取り、更新、削除など)、およびストリームの操作が含まれます。 コントロールプレーンの操作では、次のツールを使用してテーブルを作成および管理します-

  • CreateTable
  • DescribeTable
  • ListTables
  • UpdateTable
  • DeleteTable

データプレーンでは、次のツールを使用してCRUD操作を実行します-

Create Read Update Delete

PutItem

BatchWriteItem

a

GetItem

BatchGetItem

問い合わせ

Scan

UpdateItem

DeleteItem

BatchWriteItem

ストリーム操作はテーブルストリームを制御します。 次のストリームツールを確認できます-

  • ListStreams
  • DescribeStream
  • GetShardIterator
  • GetRecords

プロビジョニングされたスループット

テーブルの作成では、プロビジョニングされたスループットを指定します。これにより、読み取りおよび書き込み用のリソースが予約されます。 容量単位を使用して、スループットを測定および設定します。

アプリケーションが設定されたスループットを超えると、要求は失敗します。 DynamoDB GUIコンソールを使用すると、設定済みおよび使用済みのスループットを監視して、より優れた動的なプロビジョニングを実現できます。

一貫性の読み取り

DynamoDBは、動的アプリケーションのニーズをサポートするために、 _ eventually consistent_ および strongly consistent 読み取りを使用します。 最終的に一貫した読み取りでは、常に現在のデータが配信されるとは限りません。

強い整合性のある読み取りは、常に最新のデータを提供します(機器の障害またはネットワークの問題を除く)。 最終的に整合性のある読み取りがデフォルト設定として機能し、 ConsistentRead パラメーターをtrueに設定して変更する必要があります。

パーティション

DynamoDBは、データストレージにパーティションを使用します。 これらのテーブルのストレージ割り当てには、SSDバッキングがあり、ゾーン間で自動的に複製されます。 DynamoDBはすべてのパーティションタスクを管理するため、ユーザーの関与は必要ありません。

テーブルの作成では、テーブルはCREATING状態になり、パーティションが割り当てられます。 ACTIVE状態に達すると、操作を実行できます。 システムは、容量が最大に達するか、スループットを変更するとパーティションを変更します。

DynamoDB-環境

DynamoDB環境は、Amazon Webサービスアカウントを使用してDynamoDB GUIコンソールにアクセスするだけで構成されていますが、ローカルインストールを実行することもできます。

次のWebサイトに移動します-https://aws.amazon.com/dynamodb/

「Amazon DynamoDBの使用開始」ボタンをクリックするか、Amazon Web Servicesアカウントがない場合は「AWSアカウントの作成」ボタンをクリックします。 簡単なガイド付きプロセスにより、関連するすべての料金と要件が通知されます。

プロセスに必要なすべてのステップを実行すると、アクセスできるようになります。 AWSコンソールにサインインしてから、DynamoDBコンソールに移動します。

関連する料金を回避するために、未使用または不要な素材を必ず削除してください。

ローカルインストール

AWS(Amazon Web Service)は、ローカルインストール用のDynamoDBのバージョンを提供します。 Webサービスまたは接続なしのアプリケーションの作成をサポートします。 また、ローカルデータベースを許可することにより、プロビジョニングされたスループット、データストレージ、および転送料金を削減します。 このガイドでは、ローカルインストールを想定しています。

デプロイの準備ができたら、アプリケーションを少し調整してAWS使用に変換できます。

インストールファイルは* .jar実行可能ファイル*です。 Linux、Unix、Windows、およびJavaがサポートされているその他のOSで実行されます。 次のリンクのいずれかを使用してファイルをダウンロードします-

_ -他のリポジトリがファイルを提供しますが、必ずしも最新バージョンではありません。 最新のインストールファイルについては、上記のリンクを使用してください。 また、Java Runtime Engine(JRE)バージョン6.x以降を使用していることを確認してください。 DynamoDBは古いバージョンでは実行できません。

適切なアーカイブをダウンロードした後、そのディレクトリ(DynamoDBLocal.jar)を抽出し、目的の場所に配置します。

その後、コマンドプロンプトを開き、DynamoDBLocal.jarを含むディレクトリに移動し、次のコマンドを入力して、DynamoDBを起動できます-

java -Djava.library.path=./DynamoDBLocal_lib -jar DynamoDBLocal.jar -sharedDb

また、起動に使用したコマンドプロンプトを閉じてDynamoDBを停止することもできます。

作業環境

JavaScriptシェル、GUIコンソール、および複数の言語を使用して、DynamoDBを操作できます。 利用可能な言語には、Ruby、Java、Python、C#、Erlang、PHP、およびPerlが含まれます。

このチュートリアルでは、JavaおよびGUIコンソールの例を使用して、概念とコードを明確にします。 Javaを利用するには、Java IDE、Java用AWS SDKをインストールし、Java SDKのAWSセキュリティ認証情報を設定します。

ローカルからWebサービスコードへの変換

展開の準備ができたら、コードを変更する必要があります。 調整は、コード言語およびその他の要因に依存します。 主な変更点は、 _ endpoint_ をローカルポイントからAWSリージョンに変更することだけです。 その他の変更には、アプリケーションのより深い分析が必要です。

ローカルインストールは、次の重要な違いを含むがこれらに限定されない多くの点でWebサービスとは異なります-

  • ローカルインストールではテーブルがすぐに作成されますが、サービスにはさらに時間がかかります。
  • ローカルインストールはスループットを無視します。
  • 削除はローカルインストールですぐに行われます。
  • 読み取り/書き込みは、ネットワークオーバーヘッドがないため、ローカルインストールですばやく発生します。

DynamoDB-運用ツール

DynamoDBには、操作を実行するための3つのオプションがあります。WebベースのGUIコンソール、JavaScriptシェル、お好みのプログラミング言語です。

このチュートリアルでは、GUIコンソールとJava言語を使用して、わかりやすく概念を理解することに焦点を当てます。

GUIコンソール

GUIコンソールまたはAmazon DynamoDBのAWSマネジメントコンソールは、次のアドレスで見つけることができます-https://console.aws.amazon.com/dynamodb/home

それはあなたが次のタスクを実行することができます-

  • CRUD
  • テーブルアイテムの表示
  • テーブルクエリを実行する
  • テーブル容量監視のアラームを設定する
  • リアルタイムでテーブルメトリックを表示する
  • テーブルアラームの表示

GUIコンソール

DynamoDBアカウントにテーブルがない場合、アクセス時に、テーブルの作成をガイドします。 メイン画面には、一般的な操作を実行するための3つのショートカットがあります-

  • テーブルを作成する
  • テーブルの追加とクエリ *テーブルの監視と管理

JavaScriptシェル

DynamoDBには、インタラクティブなJavaScriptシェルが含まれています。 シェルはWebブラウザー内で実行され、推奨されるブラウザーにはFirefoxおよびChromeが含まれます。

JavaScript Shell

* 注*-他のブラウザを使用するとエラーが発生する場合があります。

Webブラウザーを開き、次のアドレスを入力してシェルにアクセスします-* http://localhost:8000/shell *

左ペインにJavaScriptを入力し、左ペインの右上隅にある[再生]アイコンボタンをクリックして、コードを実行することにより、シェルを使用します。 コード結果が右側のペインに表示されます。

DynamoDBとJava

Java開発環境を利用して、DynamoDBでJavaを使用します。 操作は、通常のJava構文と構造を確認します。

DynamoDB-データ型

DynamoDBがサポートするデータ型には、属性、アクション、および選択したコーディング言語に固有のものが含まれます。

属性データ型

DynamoDBは、テーブル属性の多数のデータ型セットをサポートしています。 各データ型は、次の3つのカテゴリのいずれかに分類されます-

  • スカラー-これらのタイプは単一の値を表し、数値、文字列、バイナリ、ブール、およびヌルが含まれます。
  • ドキュメント-これらのタイプは、ネストされた属性を持つ複雑な構造を表し、リストとマップを含みます。
  • セット-これらのタイプは複数のスカラーを表し、文字列セット、数値セット、およびバイナリセットを含みます。

DynamoDBは、テーブルを作成するときに属性やデータ型の定義を必要としない、スキーマレスのNoSQLデータベースとして覚えておいてください。 テーブル作成時に列データ型を必要とするRDBMSとは対照的に、主キー属性データ型のみが必要です。

スカラー

  • 数字-38桁に制限されており、正、負、またはゼロです。
  • 文字列-UTF-8を使用したUnicodeで、最小長が0以上、最大400KBです。
  • Binary -暗号化されたデータ、画像、圧縮テキストなどのバイナリデータを保存します。 DynamoDBは、そのバイトを符号なしと見なします。
  • ブール-彼らはtrueまたはfalseを格納します。
  • Null -不明または未定義の状態を表します。

資料

  • リスト-順序付けられた値のコレクションを保存し、角括弧([…​])を使用します。
  • Map -順序付けられていない名前と値のペアのコレクションを保存し、中括弧(\ {…​})を使用します。

Set

セットには、数値、文字列、またはバイナリにかかわらず、同じタイプの要素が含まれている必要があります。 セットに設定される唯一の制限は、400KBのアイテムサイズ制限で構成され、各要素は一意です。

アクションデータタイプ

DynamoDB APIは、アクションで使用されるさまざまなデータ型を保持します。 あなたは、次のキータイプの選択を確認することができます-

  • AttributeDefinition -キーテーブルとインデックススキーマを表します。
  • 容量-テーブルまたはインデックスによって消費されるスループットの量を表します。
  • CreateGlobalSecondaryIndexAction -テーブルに追加された新しいグローバルセカンダリインデックスを表します。
  • LocalSecondaryIndex -ローカルセカンダリインデックスのプロパティを表します。
  • ProvisionedThroughput -インデックスまたはテーブルのプロビジョニングされたスループットを表します。
  • PutRequest -PutItemリクエストを表します。
  • TableDescription -テーブルのプロパティを表します。

サポートされているJavaデータ型

DynamoDBは、プリミティブデータ型、Setコレクション、およびJavaの任意の型のサポートを提供します。

DynamoDB-テーブルの作成

通常、テーブルの作成は、テーブルの生成、名前の付け、主キー属性の確立、および属性データ型の設定で構成されます。

GUIコンソール、Java、または別のオプションを使用して、これらのタスクを実行します。

GUIコンソールを使用してテーブルを作成する

https://console.aws.amazon.com/dynamodbでコンソールにアクセスして、テーブルを作成します。 次に、「テーブルの作成」オプションを選択します。

GUIコンソール

この例では、ID番号(数値属性)で識別される一意の属性の製品とともに、製品情報が入力されたテーブルを生成します。 [テーブルの作成]画面で、テーブル名フィールドにテーブル名を入力します。パーティションキーフィールド内にプライマリキー(ID)を入力します。データタイプに「Number」と入力します。

テーブルの作成

すべての情報を入力したら、*作成*を選択します。

Javaを使用してテーブルを作成する

Javaを使用して同じテーブルを作成します。 その主キーは、次の2つの属性で構成されています-

  • ID -パー​​ティションキーと、数値を意味するScalarAttributeType N を使用します。
  • 命名法-ソートキーと、文字列を意味するScalarAttributeType *S を使用します。

Javaは* createTableメソッド*を使用してテーブルを生成します。呼び出し内で、テーブル名、主キー属性、および属性データ型が指定されます。

次の例を確認できます-

import java.util.Arrays;

import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient;
import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.Table;

import com.amazonaws.services.dynamodbv2.model.AttributeDefinition;
import com.amazonaws.services.dynamodbv2.model.KeySchemaElement;
import com.amazonaws.services.dynamodbv2.model.KeyType;
import com.amazonaws.services.dynamodbv2.model.ProvisionedThroughput;
import com.amazonaws.services.dynamodbv2.model.ScalarAttributeType;

public class ProductsCreateTable {
   public static void main(String[] args) throws Exception {
      AmazonDynamoDBClient client = new AmazonDynamoDBClient()
         .withEndpoint("http://localhost:8000");

      DynamoDB dynamoDB = new DynamoDB(client);
      String tableName = "Products";
      try {
         System.out.println("Creating the table, wait...");
         Table table = dynamoDB.createTable (tableName,
            Arrays.asList (
               new KeySchemaElement("ID", KeyType.HASH),//the partition key
                                                        //the sort key
               new KeySchemaElement("Nomenclature", KeyType.RANGE)
            ),
            Arrays.asList (
               new AttributeDefinition("ID", ScalarAttributeType.N),
               new AttributeDefinition("Nomenclature", ScalarAttributeType.S)
            ),
            new ProvisionedThroughput(10L, 10L)
         );
         table.waitForActive();
         System.out.println("Table created successfully.  Status: " +
            table.getDescription().getTableStatus());

      } catch (Exception e) {
         System.err.println("Cannot create the table: ");
         System.err.println(e.getMessage());
      }
   }
}

上記の例では、エンドポイントに注意してください: .withEndpoint

ローカルホストを使用してローカルインストールを使用することを示します。 また、ローカルインストールでは無視される必須の* ProvisionedThroughputパラメーター*にも注意してください。

DynamoDB-テーブルのロード

通常、テーブルのロードでは、ソースファイルを作成し、ソースファイルがDynamoDBと互換性のある構文に準拠していることを確認し、ソースファイルを宛先に送信し、成功したことを確認します。

GUIコンソール、Java、または別のオプションを使用してタスクを実行します。

GUIコンソールを使用したテーブルのロード

コマンドラインとコンソールの組み合わせを使用してデータをロードします。 あなたは複数の方法でデータをロードすることができ、そのうちのいくつかは次のとおりです-

  • コンソール
  • コマンドライン
  • コードも
  • データパイプライン(チュートリアルで後述する機能)

ただし、速度のために、この例ではシェルとコンソールの両方を使用しています。 まず、次の構文でソースデータを宛先にロードします-

aws dynamodb batch-write-item -–request-items file://[filename]

たとえば-

aws dynamodb batch-write-item -–request-items file://MyProductData.json

コンソールにアクセスして、操作の成功を確認します-

https://console.aws.amazon.com/dynamodb

ナビゲーションペインから[テーブル]を選択し、テーブルリストから宛先テーブルを選択します。

*Items* タブを選択して、テーブルの設定に使用したデータを調べます。 [キャンセル]を選択して、テーブルリストに戻ります。

Javaを使用してテーブルをロードする

最初にソースファイルを作成して、Javaを使用します。 ソースファイルはJSON形式を使用します。 各製品には、2つの主キー属性(IDと命名法)とJSONマップ(統計)があります-

[
   {
      "ID" : ... ,
      "Nomenclature" : ... ,
      "Stat" : { ... }
   },
   {
      "ID" : ... ,
      "Nomenclature" : ... ,
      "Stat" : { ... }
   },
    ...
]

次の例を確認できます-

{
   "ID" : 122,
   "Nomenclature" : "Particle Blaster 5000",
   "Stat" : {
      "Manufacturer" : "XYZ Inc.",
      "sales" : "1M+",
      "quantity" : 500,
      "img_src" : "http://www.xyz.com/manuals/particleblaster5000.jpg",
      "description" : "A laser cutter used in plastic manufacturing."
   }
}

次のステップは、アプリケーションが使用するディレクトリにファイルを配置することです。

Javaは主に putItem および* pathメソッド*を使用してロードを実行します。

ファイルを処理してロードするための次のコード例を確認できます-

import java.io.File;
import java.util.Iterator;

import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient;
import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.Item;
import com.amazonaws.services.dynamodbv2.document.Table;

import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.databind.node.ObjectNode;

public class ProductsLoadData {
   public static void main(String[] args) throws Exception {
      AmazonDynamoDBClient client = new AmazonDynamoDBClient()
         .withEndpoint("http://localhost:8000");

      DynamoDB dynamoDB = new DynamoDB(client);
      Table table = dynamoDB.getTable("Products");
      JsonParser parser = new JsonFactory()
         .createParser(new File("productinfo.json"));

      JsonNode rootNode = new ObjectMapper().readTree(parser);
      Iterator<JsonNode> iter = rootNode.iterator();
      ObjectNode currentNode;

      while (iter.hasNext()) {
         currentNode = (ObjectNode) iter.next();
         int ID = currentNode.path("ID").asInt();
         String Nomenclature = currentNode.path("Nomenclature").asText();

         try {
            table.putItem(new Item()
               .withPrimaryKey("ID", ID, "Nomenclature", Nomenclature)
               .withJSON("Stat", currentNode.path("Stat").toString()));
            System.out.println("Successful load: " + ID + " " + Nomenclature);
         } catch (Exception e) {
            System.err.println("Cannot add product: " + ID + " " + Nomenclature);
            System.err.println(e.getMessage());
            break;
         }
      }
      parser.close();
   }
}

DynamoDB-クエリテーブル

テーブルのクエリには、主にテーブルの選択、パーティションキーの指定、クエリの実行が必要です。セカンダリインデックスを使用し、スキャン操作でより深いフィルタリングを実行するオプションがあります。

GUIコンソール、Java、または別のオプションを使用してタスクを実行します。

GUIコンソールを使用したクエリテーブル

以前に作成したテーブルを使用していくつかの簡単なクエリを実行します。 まず、https://console.aws.amazon.com/dynamodb/[https://console.aws.amazon.com/dynamodb]でコンソールを開きます。

ナビゲーションペインから[テーブル]を選択し、テーブルリストから[返信]を選択します。 次に、 Items タブを選択して、ロードされたデータを表示します。

[アイテムの作成]ボタンの下のデータフィルタリングリンク(「スキャン:[テーブル]返信」)を選択します。

GUIコンソールを使用したクエリテーブル

フィルタリング画面で、操作の[クエリ]を選択します。 適切なパーティションキー値を入力し、[開始]をクリックします。

*Reply* テーブルは、一致するアイテムを返します。

返信テーブル

Javaを使用したクエリテーブル

Javaのクエリメソッドを使用して、データ取得操作を実行します。 パーティションキーの値を指定する必要があり、オプションとしてソートキーがあります。

最初にパラメーターを記述する* querySpecオブジェクト*を作成して、Javaクエリをコーディングします。 次に、オブジェクトをクエリメソッドに渡します。 前の例のパーティションキーを使用します。

次の例を確認できます-

import java.util.HashMap;
import java.util.Iterator;

import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient;
import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.Item;
import com.amazonaws.services.dynamodbv2.document.ItemCollection;
import com.amazonaws.services.dynamodbv2.document.QueryOutcome;
import com.amazonaws.services.dynamodbv2.document.Table;
import com.amazonaws.services.dynamodbv2.document.spec.QuerySpec;
import com.amazonaws.services.dynamodbv2.document.utils.NameMap;

public class ProductsQuery {
   public static void main(String[] args) throws Exception {
      AmazonDynamoDBClient client = new AmazonDynamoDBClient()
         .withEndpoint("http://localhost:8000");

      DynamoDB dynamoDB = new DynamoDB(client);
      Table table = dynamoDB.getTable("Products");
      HashMap<String, String> nameMap = new HashMap<String, String>();
      nameMap.put("#ID", "ID");
      HashMap<String, Object> valueMap = new HashMap<String, Object>();
      valueMap.put(":xxx", 122);
      QuerySpec querySpec = new QuerySpec()
         .withKeyConditionExpression("#ID = :xxx")
         .withNameMap(new NameMap().with("#ID", "ID"))
         .withValueMap(valueMap);

      ItemCollection<QueryOutcome> items = null;
      Iterator<Item> iterator = null;
      Item item = null;
      try {
         System.out.println("Product with the ID 122");
         items = table.query(querySpec);
         iterator = items.iterator();

         while (iterator.hasNext()) {
            item = iterator.next();
            System.out.println(item.getNumber("ID") + ": "
               + item.getString("Nomenclature"));
         }
      } catch (Exception e) {
         System.err.println("Cannot find products with the ID number 122");
         System.err.println(e.getMessage());
      }
   }
}

クエリはパーティションキーを使用しますが、セカンダリインデックスはクエリの別のオプションを提供することに注意してください。 この柔軟性により、非キー属性のクエリが可能になります。これについては、このチュートリアルの後半で説明します。

scanメソッドは、すべてのテーブルデータを収集することにより、取得操作もサポートします。 *オプションの.withFilterExpression *は、指定された基準外のアイテムが結果に表示されないようにします。

このチュートリアルの後半で、*スキャン*について詳しく説明します。 今、次の例を見てみましょう-

import java.util.Iterator;

import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient;
import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.Item;
import com.amazonaws.services.dynamodbv2.document.ItemCollection;
import com.amazonaws.services.dynamodbv2.document.ScanOutcome;
import com.amazonaws.services.dynamodbv2.document.Table;
import com.amazonaws.services.dynamodbv2.document.spec.ScanSpec;
import com.amazonaws.services.dynamodbv2.document.utils.NameMap;
import com.amazonaws.services.dynamodbv2.document.utils.ValueMap;

public class ProductsScan {
   public static void main(String[] args) throws Exception {
      AmazonDynamoDBClient client = new AmazonDynamoDBClient()
         .withEndpoint("http://localhost:8000");

      DynamoDB dynamoDB = new DynamoDB(client);
      Table table = dynamoDB.getTable("Products");
      ScanSpec scanSpec = new ScanSpec()
         .withProjectionExpression("#ID, Nomenclature , stat.sales")
         .withFilterExpression("#ID between :start_id and :end_id")
         .withNameMap(new NameMap().with("#ID",  "ID"))
         .withValueMap(new ValueMap().withNumber(":start_id", 120)
         .withNumber(":end_id", 129));

      try {
         ItemCollection<ScanOutcome> items = table.scan(scanSpec);
         Iterator<Item> iter = items.iterator();

         while (iter.hasNext()) {
            Item item = iter.next();
            System.out.println(item.toString());
         }
      } catch (Exception e) {
         System.err.println("Cannot perform a table scan:");
         System.err.println(e.getMessage());
      }
   }
}

DynamoDB-テーブルの削除

この章では、テーブルを削除する方法と、テーブルを削除するさまざまな方法について説明します。

テーブルの削除は、テーブル名以外はほとんど必要としない単純な操作です。 GUIコンソール、Java、またはその他のオプションを使用して、このタスクを実行します。

GUIコンソールを使用したテーブルの削除

最初にコンソールにアクセスして削除操作を実行します-

[[2]]

ナビゲーションペインから[テーブル]を選択し、次のスクリーンショットに示すように、テーブルリストから削除するテーブルを選択します。

GUIコンソールを使用したテーブルの削除

最後に、*テーブルの削除*を選択します。 [テーブルの削除]を選択すると、確認が表示されます。 その後、テーブルが削除されます。

Javaを使用してテーブルを削除する

*delete* メソッドを使用して、テーブルを削除します。 概念をよりよく説明するための例を以下に示します。
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient;
import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.Table;

public class ProductsDeleteTable {
   public static void main(String[] args) throws Exception {
      AmazonDynamoDBClient client = new AmazonDynamoDBClient()
         .withEndpoint("http://localhost:8000");

      DynamoDB dynamoDB = new DynamoDB(client);
      Table table = dynamoDB.getTable("Products");
      try {
         System.out.println("Performing table delete, wait...");
         table.delete();
         table.waitForDelete();
         System.out.print("Table successfully deleted.");
      } catch (Exception e) {
         System.err.println("Cannot perform table delete: ");
         System.err.println(e.getMessage());
      }
   }
}

DynamoDB-APIインターフェイス

DynamoDBは、テーブル操作、データ読み取り、データ変更のための強力なAPIツールの幅広いセットを提供します。

Amazonは、低レベルAPIを呼び出すのではなく、 AWS SDK (Java SDKなど)を使用することをお勧めします。 ライブラリにより、低レベルAPIとの対話が直接不要になります。 ライブラリは、認証、シリアル化、接続などの一般的なタスクを簡素化します。

テーブルを操作する

DynamoDBは、テーブル管理用に5つの低レベルアクションを提供します-

  • CreateTable -これによりテーブルが生成され、ユーザーが設定したスループットが含まれます。 複合または単純にかかわらず、主キーを設定する必要があります。 また、1つまたは複数のセカンダリインデックスを許可します。
  • ListTables -これは、現在のAWSユーザーのアカウント内のすべてのテーブルのリストを提供し、エンドポイントに関連付けられています。
  • UpdateTable -これはスループットとグローバルセカンダリインデックスのスループットを変更します。
  • DescribeTable -これはテーブルのメタデータを提供します。たとえば、状態、サイズ、インデックス。
  • DeleteTable -これは単にテーブルとそのインデックスを消去します。

データを読む

DynamoDBは、データ読み取り用に4つの低レベルアクションを提供します-

  • GetItem -主キーを受け入れ、関連するアイテムの属性を返します。 デフォルトの最終的に一貫した読み取り設定の変更を許可します。
  • BatchGetItem -1つまたは複数のテーブルのオプションを使用して、主キーを介して複数のアイテムで複数のGetItem要求を実行します。 その返品は100アイテム以下であり、16MB未満でなければなりません。 最終的に一貫した読み取りと強い一貫性のある読み取りが可能になります。
  • スキャン-すべてのテーブル項目を読み取り、最終的に一貫した結果セットを生成します。 条件によって結果をフィルタリングできます。 インデックスの使用を避け、テーブル全体をスキャンするため、予測可能性が必要なクエリには使用しないでください。
  • クエリ-単一または複数のテーブルアイテムまたはセカンダリインデックスアイテムを返します。 パーティションキーに指定された値を使用し、比較演算子を使用して範囲を絞り込むことができます。 両方のタイプの一貫性のサポートが含まれており、各応答はサイズが1MBの制限に従います。

データを修正する

DynamoDBは、データ変更のために4つの低レベルアクションを提供します-

  • PutItem -これは、新しいアイテムを生成するか、既存のアイテムを置き換えます。 同一のプライマリキーが検出されると、デフォルトでアイテムが置き換えられます。 条件演算子を使用すると、デフォルトを回避し、特定の条件下でのみアイテムを置換できます。
  • BatchWriteItem -これは、複数のPutItem要求とDeleteItem要求の両方を実行し、複数のテーブルで実行します。 1つの要求が失敗しても、操作全体には影響しません。 キャップのサイズは25アイテム、サイズは16MBです。
  • UpdateItem -既存のアイテム属性を変更し、特定の条件下でのみ更新を実行する条件演算子の使用を許可します。
  • DeleteItem -主キーを使用してアイテムを消去し、条件演算子を使用して削除条件を指定することもできます。

DynamoDB-アイテムの作成

DynamoDBでアイテムを作成するには、主にアイテムと属性の指定、および条件を指定するオプションが含まれます。 各アイテムは一連の属性として存在し、各属性には名前が付けられ、特定のタイプの値が割り当てられます。

値タイプには、スカラー、ドキュメント、またはセットが含まれます。 アイテムには400KBのサイズ制限があり、その制限内に収まる属性がいくつでもある可能性があります。 名前と値のサイズ(バイナリおよびUTF-8の長さ)により、アイテムのサイズが決まります。 短い属性名を使用すると、アイテムのサイズを最小限に抑えることができます。

_ -すべてのプライマリキー属性を指定する必要があります。プライマリキーにはパーティションキーのみが必要です。パーティションキーとソートキーの両方を必要とする複合キー。

また、テーブルには事前定義されたスキーマがないことを忘れないでください。 1つのテーブルに劇的に異なるデータセットを保存できます。

このタスクを実行するには、GUIコンソール、Java、または別のツールを使用します。

GUIコンソールを使用してアイテムを作成する方法

コンソールに移動します。 左側のナビゲーションペインで、テーブル*を選択します。 宛先として使用するテーブル名を選択し、次のスクリーンショットに示すように[*アイテム]タブを選択します。

アイテムの作成

  • アイテムの作成*を選択します。 [アイテムの作成]画面には、必要な属性値を入力するためのインターフェイスがあります。 セカンダリインデックスも入力する必要があります。

アイテムの作成を選択

さらに属性が必要な場合は、メッセージ*の左側にあるアクションメニューを選択します。 次に、*追加、および目的のデータ型を選択します。

メッセージ

すべての重要な情報を入力したら、[保存]を選択してアイテムを追加します。

アイテム作成でJavaを使用する方法

アイテム作成操作でJavaを使用するには、DynamoDBクラスインスタンス、テーブルクラスインスタンス、アイテムクラスインスタンスを作成し、作成するアイテムのプライマリキーと属性を指定します。 次に、putItemメソッドを使用して新しいアイテムを追加します。

DynamoDB dynamoDB = new DynamoDB (new AmazonDynamoDBClient(
   new ProfileCredentialsProvider()));
Table table = dynamoDB.getTable("ProductList");

//Spawn a related items list
List<Number> RELItems = new ArrayList<Number>();
RELItems.add(123);
RELItems.add(456);
RELItems.add(789);

//Spawn a product picture map
Map<String, String> photos = new HashMap<String, String>();
photos.put("Anterior", "http://xyz.com/products/101_front.jpg");
photos.put("Posterior", "http://xyz.com/products/101_back.jpg");
photos.put("Lateral", "http://xyz.com/products/101_LFTside.jpg");

//Spawn a product review map
Map<String, List<String>> prodReviews = new HashMap<String, List<String>>();
List<String> fiveStarRVW = new ArrayList<String>();
fiveStarRVW.add("Shocking high performance.");
fiveStarRVW.add("Unparalleled in its market.");
prodReviews.put("5 Star", fiveStarRVW);
List<String> oneStarRVW = new ArrayList<String>();
oneStarRVW.add("The worst offering in its market.");
prodReviews.put("1 Star", oneStarRVW);

//Generate the item
Item item = new Item()
   .withPrimaryKey("Id", 101)
   .withString("Nomenclature", "PolyBlaster 101")
   .withString("Description", "101 description")
   .withString("Category", "Hybrid Power Polymer Cutter")
   .withString("Make", "Brand – XYZ")
   .withNumber("Price", 50000)
   .withString("ProductCategory", "Laser Cutter")
   .withBoolean("Availability", true)
   .withNull("Qty")
   .withList("ItemsRelated", RELItems)
   .withMap("Images", photos)
   .withMap("Reviews", prodReviews);

//Add item to the table
PutItemOutcome outcome = table.putItem(item);

次の大きな例を見ることもできます。

_ -次のサンプルでは、​​以前に作成されたデータソースを想定しています。 実行を試みる前に、サポートライブラリを取得し、必要なデータソース(必要な特性を持つテーブル、または他の参照ソース)を作成します。

次のサンプルでは、​​Eclipse IDE、AWS認証情報ファイル、およびEclipse AWS Javaプロジェクト内のAWS Toolkitも使用しています。

package com.amazonaws.codesamples.document;

import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;

import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient;
import com.amazonaws.services.dynamodbv2.document.DeleteItemOutcome;
import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.Item;
import com.amazonaws.services.dynamodbv2.document.Table;

import com.amazonaws.services.dynamodbv2.document.UpdateItemOutcome;
import com.amazonaws.services.dynamodbv2.document.spec.DeleteItemSpec;
import com.amazonaws.services.dynamodbv2.document.spec.UpdateItemSpec;
import com.amazonaws.services.dynamodbv2.document.utils.NameMap;
import com.amazonaws.services.dynamodbv2.document.utils.ValueMap;
import com.amazonaws.services.dynamodbv2.model.ReturnValue;

public class CreateItemOpSample {
   static DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient (
      new ProfileCredentialsProvider()));
   static String tblName = "ProductList";

   public static void main(String[] args) throws IOException {
      createItems();
      retrieveItem();

     //Execute updates
      updateMultipleAttributes();
      updateAddNewAttribute();
      updateExistingAttributeConditionally();

     //Item deletion
      deleteItem();
   }
   private static void createItems() {
      Table table = dynamoDB.getTable(tblName);
      try {
         Item item = new Item()
            .withPrimaryKey("ID", 303)
            .withString("Nomenclature", "Polymer Blaster 4000")
            .withStringSet( "Manufacturers",
            new HashSet<String>(Arrays.asList("XYZ Inc.", "LMNOP Inc.")))
            .withNumber("Price", 50000)
            .withBoolean("InProduction", true)
            .withString("Category", "Laser Cutter");

         table.putItem(item);
         item = new Item()
            .withPrimaryKey("ID", 313)
            .withString("Nomenclature", "Agitatatron 2000")
            .withStringSet( "Manufacturers",
            new HashSet<String>(Arrays.asList("XYZ Inc,", "CDE Inc.")))
            .withNumber("Price", 40000)
            .withBoolean("InProduction", true)
            .withString("Category", "Agitator");

         table.putItem(item);
      } catch (Exception e) {
         System.err.println("Cannot create items.");
         System.err.println(e.getMessage());
      }
   }
}

DynamoDB-アイテムの取得

DynamoDBでアイテムを取得するには、GetItemを使用し、テーブル名とアイテムの主キーを指定する必要があります。 一部を省略するのではなく、完全な主キーを含めるようにしてください。

たとえば、複合キーのソートキーを省略します。

GetItemの動作は3つのデフォルトに準拠しています-

  • 最終的に一貫した読み取りとして実行されます。
  • すべての属性を提供します。
  • 容量単位の消費は詳述しません。

これらのパラメーターを使用すると、デフォルトのGetItemの動作をオーバーライドできます。

アイテムを取得する

DynamoDBは、複数のサーバー間でアイテムの複数のコピーを維持することにより、信頼性を確保します。 書き込みが成功するたびにこれらのコピーが作成されますが、実行にはかなりの時間がかかります。最終的に一貫性を意味します。 つまり、アイテムを書き込んだ後すぐに読み取りを試みることはできません。

GetItemのデフォルトの最終的に整合性のある読み取りを変更できますが、現在のデータのコストは依然として容量ユニットの消費になります。具体的には、2倍です。 注DynamoDBは通常、1秒以内にすべてのコピーで一貫性を実現します。

GUIコンソール、Java、または別のツールを使用して、このタスクを実行できます。

Javaを使用したアイテムの取得

アイテム取得操作でJavaを使用するには、DynamoDBクラスインスタンス、テーブルクラスインスタンスを作成し、テーブルインスタンスのgetItemメソッドを呼び出す必要があります。 次に、アイテムの主キーを指定します。

次の例を確認できます-

DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient(
   new ProfileCredentialsProvider()));
Table table = dynamoDB.getTable("ProductList");
Item item = table.getItem("IDnum", 109);

場合によっては、この操作のパラメーターを指定する必要があります。

次の例では、検索仕様に .withProjectionExpression および GetItemSpec を使用します-

GetItemSpec spec = new GetItemSpec()
   .withPrimaryKey("IDnum", 122)
   .withProjectionExpression("IDnum, EmployeeName, Department")
   .withConsistentRead(true);

Item item = table.getItem(spec);
System.out.println(item.toJSONPretty());

理解を深めるために、次の大きな例を確認することもできます。

-次のサンプルでは、​​以前に作成されたデータソースを想定しています。 実行を試みる前に、サポートライブラリを取得し、必要なデータソース(必要な特性を備えたテーブル、または他の参照ソース)を作成します。

このサンプルでは、​​Eclipse IDE、AWS認証情報ファイル、およびEclipse AWS Javaプロジェクト内のAWS Toolkitも使用します。

package com.amazonaws.codesamples.document;

import java.io.IOException
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;

import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient;
import com.amazonaws.services.dynamodbv2.document.DeleteItemOutcome;
import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.Item;
import com.amazonaws.services.dynamodbv2.document.Table;

import com.amazonaws.services.dynamodbv2.document.UpdateItemOutcome;
import com.amazonaws.services.dynamodbv2.document.spec.DeleteItemSpec;
import com.amazonaws.services.dynamodbv2.document.spec.UpdateItemSpec;
import com.amazonaws.services.dynamodbv2.document.utils.NameMap;
import com.amazonaws.services.dynamodbv2.document.utils.ValueMap;
import com.amazonaws.services.dynamodbv2.model.ReturnValue;

public class GetItemOpSample {
   static DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient(
      new ProfileCredentialsProvider()));

   static String tblName = "ProductList";
   public static void main(String[] args) throws IOException {
      createItems();
      retrieveItem();

     //Execute updates
      updateMultipleAttributes();
      updateAddNewAttribute();
      updateExistingAttributeConditionally();

     //Item deletion
      deleteItem();
   }
   private static void createItems() {
      Table table = dynamoDB.getTable(tblName);
      try {
         Item item = new Item()
            .withPrimaryKey("ID", 303)
            .withString("Nomenclature", "Polymer Blaster 4000")
            .withStringSet( "Manufacturers",
            new HashSet<String>(Arrays.asList("XYZ Inc.", "LMNOP Inc.")))
            .withNumber("Price", 50000)
            .withBoolean("InProduction", true)
            .withString("Category", "Laser Cutter");
            table.putItem(item);

         item = new Item()
            .withPrimaryKey("ID", 313)
            .withString("Nomenclature", "Agitatatron 2000")
            .withStringSet( "Manufacturers",
            new HashSet<String>(Arrays.asList("XYZ Inc,", "CDE Inc.")))
            .withNumber("Price", 40000)
            .withBoolean("InProduction", true)
            .withString("Category", "Agitator");

         table.putItem(item);
      } catch (Exception e) {
         System.err.println("Cannot create items.");
         System.err.println(e.getMessage());
      }
   }
   private static void retrieveItem() {
      Table table = dynamoDB.getTable(tableName);
      try {
         Item item = table.getItem("ID", 303, "ID, Nomenclature, Manufacturers", null);
         System.out.println("Displaying retrieved items...");
         System.out.println(item.toJSONPretty());
      } catch (Exception e) {
         System.err.println("Cannot retrieve items.");
         System.err.println(e.getMessage());
      }
   }
}

DynamoDB-アイテムの更新

DynamoDBでアイテムを更新するには、主にアイテムの完全なプライマリキーとテーブル名を指定します。 変更する属性ごとに新しい値が必要です。 操作は UpdateItem を使用します。これは、既存のアイテムを変更するか、欠落しているアイテムの発見時にそれらを作成します。

更新では、操作の前後に元の値と新しい値を表示して、変更を追跡することができます。 UpdateItemは ReturnValues パラメーターを使用してこれを実現します。

_ -操作ではキャパシティーユニットの消費は報告されませんが、 ReturnConsumedCapacity パラメーターを使用できます。

このタスクを実行するには、GUIコンソール、Java、またはその他のツールを使用します。

GUIツールを使用してアイテムを更新する方法

コンソールに移動します。 左側のナビゲーションペインで、テーブル*を選択します。 必要なテーブルを選択し、[*アイテム]タブを選択します。

GUIツールを使用してアイテムを更新

更新に必要なアイテムを選択し、[アクション]を選択します。編集

アイテムを選択

[アイテムの編集]ウィンドウで必要な属性または値を変更します。

Javaを使用してアイテムを更新する

アイテムの更新操作でJavaを使用するには、Tableクラスインスタンスを作成し、 updateItem メソッドを呼び出す必要があります。 次に、アイテムの主キーを指定し、属性の変更の詳細を示す UpdateExpression を提供します。

以下は同じ例です-

DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient(
   new ProfileCredentialsProvider()));

Table table = dynamoDB.getTable("ProductList");

Map<String, String> expressionAttributeNames = new HashMap<String, String>();
expressionAttributeNames.put("#M", "Make");
expressionAttributeNames.put("#P", "Price
expressionAttributeNames.put("#N", "ID");

Map<String, Object> expressionAttributeValues = new HashMap<String, Object>();
expressionAttributeValues.put(":val1",
   new HashSet<String>(Arrays.asList("Make1","Make2")));
expressionAttributeValues.put(":val2", 1);      //Price

UpdateItemOutcome outcome =  table.updateItem(
   "internalID",                                //key attribute name
   111,                                         //key attribute value
   "add #M :val1 set #P = #P - :val2 remove #N",//UpdateExpression
   expressionAttributeNames,
   expressionAttributeValues);
*updateItem* メソッドは、次の例で見ることができる条件を指定することもできます-
Table table = dynamoDB.getTable("ProductList");
Map<String, String> expressionAttributeNames = new HashMap<String, String>();
expressionAttributeNames.put("#P", "Price");

Map<String, Object> expressionAttributeValues = new HashMap<String, Object>();
expressionAttributeValues.put(":val1", 44); //change Price to 44
expressionAttributeValues.put(":val2", 15); //only if currently 15

UpdateItemOutcome outcome = table.updateItem (new PrimaryKey("internalID",111),
   "set #P = :val1",                       //Update
   "#P = :val2",                           //Condition
   expressionAttributeNames,
   expressionAttributeValues);

カウンターを使用してアイテムを更新する

DynamoDBではアトミックカウンターを使用できます。つまり、UpdateItemを使用して、他の要求に影響を与えることなく属性値を増減します。さらに、カウンターは常に更新されます。

以下は、その方法を説明する例です。

-次のサンプルでは、​​以前に作成されたデータソースを想定しています。 実行を試みる前に、サポートライブラリを取得し、必要なデータソース(必要な特性を備えたテーブル、または他の参照ソース)を作成します。

このサンプルでは、​​Eclipse IDE、AWS認証情報ファイル、およびEclipse AWS Javaプロジェクト内のAWS Toolkitも使用します。

package com.amazonaws.codesamples.document;

import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;

import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient;
import com.amazonaws.services.dynamodbv2.document.DeleteItemOutcome;
import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.Item;
import com.amazonaws.services.dynamodbv2.document.Table;

import com.amazonaws.services.dynamodbv2.document.UpdateItemOutcome;
import com.amazonaws.services.dynamodbv2.document.spec.DeleteItemSpec;
import com.amazonaws.services.dynamodbv2.document.spec.UpdateItemSpec;
import com.amazonaws.services.dynamodbv2.document.utils.NameMap;
import com.amazonaws.services.dynamodbv2.document.utils.ValueMap;
import com.amazonaws.services.dynamodbv2.model.ReturnValue;

public class UpdateItemOpSample {
   static DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient(
      new ProfileCredentialsProvider()));
   static String tblName = "ProductList";

   public static void main(String[] args) throws IOException {
      createItems();
      retrieveItem();

     //Execute updates
      updateMultipleAttributes();
      updateAddNewAttribute();
      updateExistingAttributeConditionally();

     //Item deletion
      deleteItem();
   }
   private static void createItems() {
      Table table = dynamoDB.getTable(tblName);
      try {
         Item item = new Item()
            .withPrimaryKey("ID", 303)
            .withString("Nomenclature", "Polymer Blaster 4000")
            .withStringSet( "Manufacturers",
            new HashSet<String>(Arrays.asList("XYZ Inc.", "LMNOP Inc.")))
            .withNumber("Price", 50000)
            .withBoolean("InProduction", true)
            .withString("Category", "Laser Cutter");
            table.putItem(item);

         item = new Item()
            .withPrimaryKey("ID", 313)
            .withString("Nomenclature", "Agitatatron 2000")
            .withStringSet( "Manufacturers",
            new HashSet<String>(Arrays.asList("XYZ Inc,", "CDE Inc.")))
            .withNumber("Price", 40000)
            .withBoolean("InProduction", true)
            .withString("Category", "Agitator");
            table.putItem(item);
      } catch (Exception e) {
         System.err.println("Cannot create items.");
         System.err.println(e.getMessage());
      }
   }
   private static void updateAddNewAttribute() {
      Table table = dynamoDB.getTable(tableName);
      try {
         Map<String, String> expressionAttributeNames = new HashMap<String, String>();
         expressionAttributeNames.put("#na", "NewAttribute");
         UpdateItemSpec updateItemSpec = new UpdateItemSpec()
            .withPrimaryKey("ID", 303)
            .withUpdateExpression("set #na = :val1")
            .withNameMap(new NameMap()
            .with("#na", "NewAttribute"))
            .withValueMap(new ValueMap()
            .withString(":val1", "A value"))
            .withReturnValues(ReturnValue.ALL_NEW);
            UpdateItemOutcome outcome =  table.updateItem(updateItemSpec);

        //Confirm
         System.out.println("Displaying updated item...");
         System.out.println(outcome.getItem().toJSONPretty());
      } catch (Exception e) {
         System.err.println("Cannot add an attribute in " + tableName);
         System.err.println(e.getMessage());
      }
   }
}

DynamoDB-アイテムの削除

DynamoDBでアイテムを削除するには、テーブル名とアイテムキーを指定するだけです。 また、間違ったアイテムを削除しないようにするために必要な条件式を使用することを強くお勧めします。

通常どおり、GUIコンソール、Java、またはその他の必要なツールを使用して、このタスクを実行できます。

GUIコンソールを使用してアイテムを削除する

コンソールに移動します。 左側のナビゲーションペインで、*テーブル*を選択します。 次に、テーブル名と[*アイテム]タブを選択します。

GUIコンソールを使用したアイテムの削除

削除するアイテムを選択し、[アクション]を選択します。削除

アクションの選択

次のスクリーンショットに示すように、[アイテムの削除]ダイアログボックスが表示されます。 「削除」を選択して確認します。

アイテムの削除

Javaを使用してアイテムを削除する方法

アイテム削除操作でJavaを使用するには、DynamoDBクライアントインスタンスを作成し、アイテムのキーを使用して deleteItem メソッドを呼び出すだけです。

詳細が説明されている次の例を見ることができます。

DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient(
   new ProfileCredentialsProvider()));

Table table = dynamoDB.getTable("ProductList");
DeleteItemOutcome outcome = table.deleteItem("IDnum", 151);

パラメーターを指定して、誤った削除から保護することもできます。 ConditionExpression を使用するだけです。

たとえば-

Map<String,Object> expressionAttributeValues = new HashMap<String,Object>();
expressionAttributeValues.put(":val", false);

DeleteItemOutcome outcome = table.deleteItem("IDnum",151,
   "Ship = :val",
   null,                  //doesn't use ExpressionAttributeNames
   expressionAttributeValues);

以下は、理解を深めるためのより大きな例です。

-次のサンプルでは、​​以前に作成されたデータソースを想定しています。 実行を試みる前に、サポートライブラリを取得し、必要なデータソース(必要な特性を備えたテーブル、または他の参照ソース)を作成します。

このサンプルでは、​​Eclipse IDE、AWS認証情報ファイル、およびEclipse AWS Javaプロジェクト内のAWS Toolkitも使用します。

package com.amazonaws.codesamples.document;

import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;

import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient;
import com.amazonaws.services.dynamodbv2.document.DeleteItemOutcome;
import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.Item;
import com.amazonaws.services.dynamodbv2.document.Table;

import com.amazonaws.services.dynamodbv2.document.UpdateItemOutcome;
import com.amazonaws.services.dynamodbv2.document.spec.DeleteItemSpec;
import com.amazonaws.services.dynamodbv2.document.spec.UpdateItemSpec;
import com.amazonaws.services.dynamodbv2.document.utils.NameMap;
import com.amazonaws.services.dynamodbv2.document.utils.ValueMap;
import com.amazonaws.services.dynamodbv2.model.ReturnValue;

public class DeleteItemOpSample {
   static DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient(
      new ProfileCredentialsProvider()));

   static String tblName = "ProductList";
   public static void main(String[] args) throws IOException {
      createItems();
      retrieveItem();

     //Execute updates
      updateMultipleAttributes();
      updateAddNewAttribute();
      updateExistingAttributeConditionally();

     //Item deletion
      deleteItem();
   }
   private static void createItems() {
      Table table = dynamoDB.getTable(tblName);
      try {
         Item item = new Item()
            .withPrimaryKey("ID", 303)
            .withString("Nomenclature", "Polymer Blaster 4000")
            .withStringSet( "Manufacturers",
            new HashSet<String>(Arrays.asList("XYZ Inc.", "LMNOP Inc.")))
            .withNumber("Price", 50000)
            .withBoolean("InProduction", true)
            .withString("Category", "Laser Cutter");
            table.putItem(item);

         item = new Item()
            .withPrimaryKey("ID", 313)
            .withString("Nomenclature", "Agitatatron 2000")
            .withStringSet( "Manufacturers",
            new HashSet<String>(Arrays.asList("XYZ Inc,", "CDE Inc.")))
            .withNumber("Price", 40000)
            .withBoolean("InProduction", true)
            .withString("Category", "Agitator");
            table.putItem(item);
      } catch (Exception e) {
         System.err.println("Cannot create items.");
         System.err.println(e.getMessage());
      }
   }
   private static void deleteItem() {
      Table table = dynamoDB.getTable(tableName);
      try {
         DeleteItemSpec deleteItemSpec = new DeleteItemSpec()
            .withPrimaryKey("ID", 303)
            .withConditionExpression("#ip = :val")
            .withNameMap(new NameMap()
            .with("#ip", "InProduction"))
            .withValueMap(new ValueMap()
            .withBoolean(":val", false))
            .withReturnValues(ReturnValue.ALL_OLD);
         DeleteItemOutcome outcome = table.deleteItem(deleteItemSpec);

        //Confirm
         System.out.println("Displaying deleted item...");
         System.out.println(outcome.getItem().toJSONPretty());
      } catch (Exception e) {
         System.err.println("Cannot delete item in " + tableName);
         System.err.println(e.getMessage());
      }
   }
}

DynamoDB-バッチ書き込み

バッチ書き込みは、複数のアイテムを作成または削除することにより、複数のアイテムで動作します。 これらの操作は、 BatchWriteItem を使用します。これには、16MBの書き込みと25のリクエストしか制限されません。 各アイテムは400KBのサイズ制限に従います。 バッチ書き込みもアイテムの更新を実行できません。

バッチライティングとは何ですか?

バッチ書き込みでは、複数のテーブルにわたってアイテムを操作できます。 操作の呼び出しは個々の要求ごとに発生します。つまり、操作は互いに影響を与えず、異種混合が許可されます。たとえば、バッチ内の1つの PutItem リクエストと3つの DeleteItem リクエストがあり、PutItemリクエストの失敗は他に影響しません。 リクエストが失敗すると、失敗した各リクエストに関連する情報(キーとデータ)が返されます。

-DynamoDBがアイテムを処理せずに返す場合、それらを再試行します。ただし、過負荷に基づく別の要求の失敗を回避するには、バックオフメソッドを使用します。

DynamoDBは、次のステートメントの1つ以上が真であることが判明した場合、バッチ書き込み操作を拒否します-

  • 要求は、プロビジョニングされたスループットを超えています。
  • リクエストは BatchWriteItems を使用してアイテムを更新しようとします。
  • 要求は、単一のアイテムに対して複数の操作を実行します。
  • 要求テーブルが存在しません。
  • リクエストのアイテム属性がターゲットと一致しません。
  • 要求がサイズ制限を超えています。

バッチ書き込みには、特定の RequestItem パラメーターが必要です-

  • 削除操作には、属性名と値を意味する DeleteRequest キー subelements が必要です。
  • PutRequest アイテムには、属性および属性値マップを意味する* Itemサブ要素*が必要です。

応答-操作が成功するとHTTP 200応答が発生します。これは、消費されたキャパシティーユニット、テーブル処理メトリック、未処理アイテムなどの特性を示します。

Javaを使用したバッチ書き込み

DynamoDBクラスインスタンス、すべての操作を記述する TableWriteItems クラスインスタンスを作成し、 batchWriteItem メソッドを呼び出してTableWriteItemsオブジェクトを使用することにより、バッチ書き込みを実行します。

-複数のテーブルへのバッチ書き込みでは、すべてのテーブルに対してTableWriteItemsインスタンスを作成する必要があります。 また、未処理のリクエストがないかリクエストレスポンスを確認してください。

次のバッチ書き込みの例を確認できます-

DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient(
   new ProfileCredentialsProvider()));

TableWriteItems forumTableWriteItems = new TableWriteItems("Forum")
   .withItemsToPut(
   new Item()
   .withPrimaryKey("Title", "XYZ CRM")
   .withNumber("Threads", 0));

TableWriteItems threadTableWriteItems = new TableWriteItems(Thread)
   .withItemsToPut(
   new Item()
   .withPrimaryKey("ForumTitle","XYZ CRM","Topic","Updates")
   .withHashAndRangeKeysToDelete("ForumTitle","A partition key value",
   "Product Line 1", "A sort key value"));

BatchWriteItemOutcome outcome = dynamoDB.batchWriteItem (
   forumTableWriteItems, threadTableWriteItems);

次のプログラムは、バッチがJavaで書き込む方法をよりよく理解するためのもう1つの大きな例です。

-次の例では、以前に作成されたデータソースを想定しています。 実行を試みる前に、サポートライブラリを取得し、必要なデータソース(必要な特性を備えたテーブル、または他の参照ソース)を作成します。

この例では、Eclipse IDE、AWS認証情報ファイル、およびEclipse AWS Javaプロジェクト内のAWS Toolkitも使用します。

package com.amazonaws.codesamples.document;

import java.io.IOException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;

import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient;
import com.amazonaws.services.dynamodbv2.document.BatchWriteItemOutcome;
import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.Item;
import com.amazonaws.services.dynamodbv2.document.TableWriteItems;
import com.amazonaws.services.dynamodbv2.model.WriteRequest;

public class BatchWriteOpSample {
   static DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient(
      new ProfileCredentialsProvider()));
   static String forumTableName = "Forum";
   static String threadTableName = "Thread";

   public static void main(String[] args) throws IOException {
      batchWriteMultiItems();
   }
   private static void batchWriteMultiItems() {
      try {
        //Place new item in Forum
         TableWriteItems forumTableWriteItems = new TableWriteItems(forumTableName)
                                                                      //Forum
            .withItemsToPut(new Item()
            .withPrimaryKey("Name", "Amazon RDS")
            .withNumber("Threads", 0));

        //Place one item, delete another in Thread
        //Specify partition key and range key
         TableWriteItems threadTableWriteItems = new TableWriteItems(threadTableName)
            .withItemsToPut(new Item()
            .withPrimaryKey("ForumName","Product
            Support","Subject","Support Thread 1")
            .withString("Message", "New OS Thread 1 message")
            .withHashAndRangeKeysToDelete("ForumName","Subject", "Polymer Blaster",
            "Support Thread 100"));

         System.out.println("Processing request...");
         BatchWriteItemOutcome outcome = dynamoDB.batchWriteItem (
               forumTableWriteItems, threadTableWriteItems);
         do {
           //Confirm no unprocessed items
            Map<String, List<WriteRequest>> unprocessedItems
               = outcome.getUnprocessedItems();

            if (outcome.getUnprocessedItems().size() == 0) {
               System.out.println("All items processed.");
            } else {
               System.out.println("Gathering unprocessed items...");
               outcome = dynamoDB.batchWriteItemUnprocessed(unprocessedItems);
            }
         } while (outcome.getUnprocessedItems().size() > 0);
      } catch (Exception e) {
         System.err.println("Could not get items: ");
         e.printStackTrace(System.err);
      }
   }
}

DynamoDB-バッチ取得

バッチ取得操作は、単一または複数のアイテムの属性を返します。 これらの操作は通常、主キーを使用して目的のアイテムを識別することで構成されます。 BatchGetItem 操作は、個々の操作の制限と独自の制約の影響を受けます。

バッチ取得操作での次のリクエストは拒否されます-

  • 100を超えるアイテムをリクエストします。
  • スループットを超える要求を行います。

バッチ取得操作は、制限を超える可能性のあるリクエストの部分処理を実行します。

たとえば-制限を超えるサイズの複数のアイテムを取得するリクエストは、リクエスト処理の一部となり、未処理部分を示すエラーメッセージが表示されます。 未処理のアイテムが返されたら、テーブルを調整するのではなく、これを管理するバックオフアルゴリズムソリューションを作成します。

*BatchGet* 操作は最終的に一貫した読み取りで実行されるため、強く一貫した読み取りを行うには変更が必要です。 また、並行して検索を実行します。

-返されるアイテムの順序。 DynamoDBはアイテムを並べ替えません。 また、要求されたアイテムが存在しないことも示しません。 さらに、これらの要求はキャパシティーユニットを消費します。

すべてのBatchGet操作には、読み取り一貫性、属性名、主キーなどの RequestItems パラメーターが必要です。

応答-操作が成功するとHTTP 200応答が発生します。これは、消費されたキャパシティーユニット、テーブル処理メトリック、未処理アイテムなどの特性を示します。

Javaを使用したバッチ取得

BatchGet操作でJavaを使用するには、DynamoDBクラスインスタンス、アイテムのプライマリキー値リストを記述する TableKeysAndAttributes クラスインスタンスを作成し、TableKeysAndAttributesオブジェクトを BatchGetItem メソッドに渡す必要があります。

以下は、BatchGet操作の例です-

DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient (
   new ProfileCredentialsProvider()));

TableKeysAndAttributes forumTableKeysAndAttributes = new TableKeysAndAttributes
   (forumTableName);

forumTableKeysAndAttributes.addHashOnlyPrimaryKeys (
   "Title",
   "Updates",
   "Product Line 1"
);
TableKeysAndAttributes threadTableKeysAndAttributes = new TableKeysAndAttributes (
   threadTableName);

threadTableKeysAndAttributes.addHashAndRangePrimaryKeys (
   "ForumTitle",
   "Topic",
   "Product Line 1",
   "P1 Thread 1",
   "Product Line 1",
   "P1 Thread 2",
   "Product Line 2",
   "P2 Thread 1"
);
BatchGetItemOutcome outcome = dynamoDB.batchGetItem (
   forumTableKeysAndAttributes, threadTableKeysAndAttributes);

for (String tableName : outcome.getTableItems().keySet()) {
   System.out.println("Table items " + tableName);
   List<Item> items = outcome.getTableItems().get(tableName);
   for (Item item : items) {
      System.out.println(item);
   }
}

次の大きな例を確認できます。

-次のプログラムは、以前に作成されたデータソースを想定している場合があります。 実行を試みる前に、サポートライブラリを取得し、必要なデータソース(必要な特性を備えたテーブル、または他の参照ソース)を作成します。

このプログラムは、Eclipse IDE、AWS認証情報ファイル、およびEclipse AWS Javaプロジェクト内のAWS Toolkitも使用します。

package com.amazonaws.codesamples.document;

import java.io.IOException;
import java.util.List;
import java.util.Map;

import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient;
import com.amazonaws.services.dynamodbv2.document.BatchGetItemOutcome;
import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.Item;
import com.amazonaws.services.dynamodbv2.document.TableKeysAndAttributes;
import com.amazonaws.services.dynamodbv2.model.KeysAndAttributes;

public class BatchGetOpSample {
   static DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient (
      new ProfileCredentialsProvider()));

   static String forumTableName = "Forum";
   static String threadTableName = "Thread";

   public static void main(String[] args) throws IOException {
      retrieveMultipleItemsBatchGet();
   }
   private static void retrieveMultipleItemsBatchGet() {
      try {
         TableKeysAndAttributes forumTableKeysAndAttributes =
            new TableKeysAndAttributes(forumTableName);

        //Create partition key
         forumTableKeysAndAttributes.addHashOnlyPrimaryKeys (
            "Name",
            "XYZ Melt-O-tron",
            "High-Performance Processing"
         );
         TableKeysAndAttributes threadTableKeysAndAttributes =
            new TableKeysAndAttributes(threadTableName);

        //Create partition key and sort key
         threadTableKeysAndAttributes.addHashAndRangePrimaryKeys (
            "ForumName",
            "Subject",
            "High-Performance Processing",
            "HP Processing Thread One",
            "High-Performance Processing",
            "HP Processing Thread Two",
            "Melt-O-Tron",
            "MeltO Thread One"
         );
         System.out.println("Processing...");
         BatchGetItemOutcome outcome = dynamoDB.batchGetItem(forumTableKeysAndAttributes,
            threadTableKeysAndAttributes);

         Map<String, KeysAndAttributes> unprocessed = null;
         do {
            for (String tableName : outcome.getTableItems().keySet()) {
               System.out.println("Table items for " + tableName);
               List<Item> items = outcome.getTableItems().get(tableName);

               for (Item item : items) {
                  System.out.println(item.toJSONPretty());
               }
            }
           //Confirm no unprocessed items
            unprocessed = outcome.getUnprocessedKeys();

            if (unprocessed.isEmpty()) {
               System.out.println("All items processed.");
            } else {
               System.out.println("Gathering unprocessed items...");
               outcome = dynamoDB.batchGetItemUnprocessed(unprocessed);
            }
         } while (!unprocessed.isEmpty());
      } catch (Exception e) {
         System.err.println("Could not get items.");
         System.err.println(e.getMessage());
      }
   }
}

DynamoDB-クエリ

クエリは、プライマリキーを通じてアイテムまたはセカンダリインデックスを検索します。 クエリを実行するには、パーティションキーと特定の値、またはソートキーと値が必要です。比較でフィルタリングするオプションがあります。 クエリのデフォルトの動作は、指定された主キーに関連付けられたアイテムのすべての属性を返すことです。 ただし、 ProjectionExpression パラメーターを使用して目的の属性を指定できます。

クエリは、 KeyConditionExpression パラメータを使用してアイテムを選択します。これには、パーティションキーの名前と値を等価条件の形式で指定する必要があります。 存在する並べ替えキーに追加条件を提供するオプションもあります。

ソートキー条件のいくつかの例は次のとおりです-

Sr.No Condition & Description
1

x = y

属性xがyに等しい場合、trueと評価されます。

2

x < y

xがyより小さい場合、trueと評価されます。

3

x ⇐ y

xがy以下の場合、trueと評価されます。

4

x > y

xがyより大きい場合、trueと評価されます。

5

x >= y

xがy以上の場合、trueと評価されます。

6

x BETWEEN y AND z

xが> = yかつ⇐ zの両方である場合、trueと評価されます。

DynamoDBは次の関数もサポートしています:* begins_with(x、substr)*

属性xが指定された文字列で始まる場合、trueと評価されます。

次の条件は、特定の要件に準拠する必要があります-

  • 属性名は、a-zまたはA-Zセット内の文字で始まる必要があります。
  • 属性名の2番目の文字は、a-z、A-Z、または0-9セットに含まれている必要があります。
  • 属性名には予約語を使用できません。

上記の制約に準拠していない属性名は、プレースホルダーを定義できます。

クエリは、ソートキー順で取得を実行し、存在する条件とフィルター式を使用して処理します。 クエリは常に結果セットを返し、一致しない場合は空の結果セットを返します。

結果は常に、ソートキーの順序、および昇順として変更可能なデフォルトを使用したデータ型ベースの順序で返されます。

Javaを使用したクエリ

Javaのクエリを使用すると、テーブルとセカンダリインデックスをクエリできます。 ソートキーと条件を指定するオプションとともに、パーティションキーと等価条件の指定が必要です。

Javaでのクエリに一般的に必要な手順には、DynamoDBクラスインスタンスの作成、ターゲットテーブルのTableクラスインスタンス、Tableオブジェクトのqueryメソッドの呼び出しによるクエリオブジェクトの受信が含まれます。

クエリへの応答には、返されたすべてのアイテムを提供する ItemCollection オブジェクトが含まれます。

次の例は、詳細なクエリを示しています-

DynamoDB dynamoDB = new DynamoDB (
   new AmazonDynamoDBClient(new ProfileCredentialsProvider()));

Table table = dynamoDB.getTable("Response");
   QuerySpec spec = new QuerySpec()
   .withKeyConditionExpression("ID = :nn")
.withValueMap(new ValueMap()
   .withString(":nn", "Product Line 1#P1 Thread 1"));

ItemCollection<QueryOutcome> items = table.query(spec);
Iterator<Item> iterator = items.iterator();
Item item = null;

while (iterator.hasNext()) {
   item = iterator.next();
   System.out.println(item.toJSONPretty());
}

クエリメソッドは、さまざまなオプションパラメータをサポートしています。 次の例は、これらのパラメータを利用する方法を示しています-

Table table = dynamoDB.getTable("Response");
QuerySpec spec = new QuerySpec()
   .withKeyConditionExpression("ID = :nn and ResponseTM > :nn_responseTM")
   .withFilterExpression("Author = :nn_author")
   .withValueMap(new ValueMap()
   .withString(":nn", "Product Line 1#P1 Thread 1")
   .withString(":nn_responseTM", twoWeeksAgoStr)
   .withString(":nn_author", "Member 123"))
   .withConsistentRead(true);

ItemCollection<QueryOutcome> items = table.query(spec);
Iterator<Item> iterator = items.iterator();

while (iterator.hasNext()) {
   System.out.println(iterator.next().toJSONPretty());
}

次の大きな例を確認することもできます。

-次のプログラムは、以前に作成されたデータソースを想定している場合があります。 実行を試みる前に、サポートライブラリを取得し、必要なデータソース(必要な特性を備えたテーブル、または他の参照ソース)を作成します。

この例では、Eclipse IDE、AWS認証情報ファイル、およびEclipse AWS Javaプロジェクト内のAWS Toolkitも使用します。

package com.amazonaws.codesamples.document;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;

import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient;
import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.Item;
import com.amazonaws.services.dynamodbv2.document.ItemCollection;

import com.amazonaws.services.dynamodbv2.document.Page;
import com.amazonaws.services.dynamodbv2.document.QueryOutcome;
import com.amazonaws.services.dynamodbv2.document.Table;
import com.amazonaws.services.dynamodbv2.document.spec.QuerySpec;
import com.amazonaws.services.dynamodbv2.document.utils.ValueMap;

public class QueryOpSample {
   static DynamoDB dynamoDB = new DynamoDB(
      new AmazonDynamoDBClient(new ProfileCredentialsProvider()));
   static String tableName = "Reply";

   public static void main(String[] args) throws Exception {
      String forumName = "PolyBlaster";
      String threadSubject = "PolyBlaster Thread 1";
      getThreadReplies(forumName, threadSubject);
   }
   private static void getThreadReplies(String forumName, String threadSubject) {
      Table table = dynamoDB.getTable(tableName);
      String replyId = forumName + "#" + threadSubject;
      QuerySpec spec = new QuerySpec()
         .withKeyConditionExpression("Id = :v_id")
         .withValueMap(new ValueMap()
         .withString(":v_id", replyId));

      ItemCollection<QueryOutcome> items = table.query(spec);
      System.out.println("\ngetThreadReplies results:");
      Iterator<Item> iterator = items.iterator();

      while (iterator.hasNext()) {
         System.out.println(iterator.next().toJSONPretty());
      }
   }
}

DynamoDB-スキャン

スキャン操作は、すべてのテーブル項目またはセカンダリインデックスを読み取ります。 そのデフォルト関数は、インデックスまたはテーブル内のすべてのアイテムのすべてのデータ属性を返します。 属性のフィルタリングに ProjectionExpression パラメーターを使用します。

一致が見つからない場合でも、すべてのスキャンは結果セットを返し、結果として空のセットになります。 スキャンは、データをフィルタリングするオプションを使用して、1MB以下を取得します。

_ -スキャンのパラメーターとフィルタリングはクエリにも適用されます。

スキャン操作の種類

フィルタリング-スキャン操作は、スキャンまたはクエリ後にデータを変更するフィルター式を使用して、細かいフィルタリングを提供します。結果を返す前。 式は比較演算子を使用します。 それらの構文は、フィルター式では許可されないキー属性を除き、条件式に似ています。 フィルター式でパーティションまたはソートキーを使用することはできません。

_ -フィルタリングを適用する前に1MBの制限が適用されます。_

スループット仕様-スキャンはスループットを消費しますが、消費は返されるデータではなくアイテムのサイズに集中します。 すべての属性を要求しても数個の属性を要求しても消費は同じままであり、フィルター式を使用しても使用しなくても消費には影響しません。

ページネーション-DynamoDBは結果をページ分割し、結果を特定のページに分割します。 返される結果には1MBの制限が適用され、それを超えると、残りのデータを収集するために別のスキャンが必要になります。 LastEvaluatedKey 値を使用すると、この後続のスキャンを実行できます。 値を ExclusiveStartkey に適用するだけです。 LastEvaluatedKey 値がnullになると、操作はデータのすべてのページを完了しました。 ただし、null以外の値は、自動的により多くのデータが残ることを意味しません。 ヌル値のみがステータスを示します。

制限パラメータ-制限パラメータは結果のサイズを管理します。 DynamoDBはこれを使用して、データを返す前に処理するアイテムの数を確立し、スコープ外では機能しません。 xの値を設定すると、DynamoDBは一致する最初のxアイテムを返します。

LastEvaluatedKey値は、部分的な結果をもたらす制限パラメーターの場合にも適用されます。 スキャンを完了するために使用します。

結果カウント-クエリおよびスキャンへの応答には、スキャン/クエリされたアイテムを定量化し、返されたアイテムを定量化する ScannedCount およびCountに関連する情報も含まれます。 フィルタリングしない場合、値は同じです。 1MBを超えると、カウントは処理された部分のみを表します。

一貫性-クエリ結果とスキャン結果は最終的に一貫した読み取りになりますが、強く一貫した読み取りを設定することもできます。 この設定を変更するには、 ConsistentRead パラメーターを使用します。

_ -一貫性のある読み取り設定は、強く一貫性が設定されている場合、2倍の容量単位を使用することで消費に影響します。

パフォーマンス-クエリは、テーブル全体またはセカンダリインデックスをクロールするため、スキャンよりもパフォーマンスが向上し、応答が遅くなり、スループットが大量に消費されます。 スキャンは小さなテーブルと少ないフィルターでの検索に最適ですが、突然の高速な読み取りアクティビティの回避や並列スキャンの活用などのいくつかのベストプラクティスに従うことで、無駄のないスキャンを設計できます。

クエリは、特定の条件を満たすキーの特定の範囲を検出します。パフォーマンスは、キーの量ではなく、取得するデータの量によって決まります。 操作のパラメーターと一致の数は、特にパフォーマンスに影響します。

並列スキャン

スキャン操作は、デフォルトで順次処理を実行します。 次に、データを1MBずつ返します。これにより、アプリケーションは次の部分をフェッチするように求められます。 これにより、大きなテーブルとインデックスを長時間スキャンします。

この特性は、スキャンが常に利用可能なスループットを十分に活用するとは限らないことも意味します。 DynamoDBは、テーブルデータを複数のパーティションに分散します。スキャンスループットは、単一パーティション操作のため、単一パーティションに制限されたままです。

この問題の解決策は、テーブルまたはインデックスを論理的にセグメントに分割することです。 次に、「ワーカー」がセグメントを並行して(同時に)スキャンします。 Segmentおよび TotalSegments のパラメーターを使用して、特定のワーカーによってスキャンされるセグメントを指定し、処理されるセグメントの合計量を指定します。

労働者番号

最高のアプリケーションパフォーマンスを実現するには、ワーカー値(Segmentパラメーター)を試す必要があります。

-大量のワーカーセットを使用した並列スキャンは、すべてのスループットを消費する可能性があるため、スループットに影響します。 この問題は、単一のワーカーがすべてのスループットを消費しないようにするために使用できるLimitパラメーターで管理します。

以下はディープスキャンの例です。

-次のプログラムは、以前に作成されたデータソースを想定している場合があります。 実行を試みる前に、サポートライブラリを取得し、必要なデータソース(必要な特性を備えたテーブル、または他の参照ソース)を作成します。

この例では、Eclipse IDE、AWS認証情報ファイル、およびEclipse AWS Javaプロジェクト内のAWS Toolkitも使用します。

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient;
import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.Item;
import com.amazonaws.services.dynamodbv2.document.ItemCollection;
import com.amazonaws.services.dynamodbv2.document.ScanOutcome;
import com.amazonaws.services.dynamodbv2.document.Table;

public class ScanOpSample {
   static DynamoDB dynamoDB = new DynamoDB(
      new AmazonDynamoDBClient(new ProfileCredentialsProvider()));
   static String tableName = "ProductList";

   public static void main(String[] args) throws Exception {
      findProductsUnderOneHun();                      //finds products under 100 dollars
   }
   private static void findProductsUnderOneHun() {
      Table table = dynamoDB.getTable(tableName);
      Map<String, Object> expressionAttributeValues = new HashMap<String, Object>();
      expressionAttributeValues.put(":pr", 100);

      ItemCollection<ScanOutcome> items = table.scan (
         "Price < :pr",                                 //FilterExpression
         "ID, Nomenclature, ProductCategory, Price",    //ProjectionExpression
         null,                                          //No ExpressionAttributeNames
         expressionAttributeValues);

      System.out.println("Scanned " + tableName + " to find items under $100.");
      Iterator<Item> iterator = items.iterator();

      while (iterator.hasNext()) {
         System.out.println(iterator.next().toJSONPretty());
      }
   }
}

DynamoDB-インデックス

DynamoDBは、主キー属性のインデックスを使用してアクセスを改善します。 アプリケーションのアクセスとデータの取得を高速化し、アプリケーションの遅延を減らすことでパフォーマンスの向上をサポートします。

二次インデックス

セカンダリインデックスは、属性サブセットと代替キーを保持します。 インデックスを対象とするクエリまたはスキャン操作で使用します。

その内容には、投影またはコピーする属性が含まれます。 作成時に、インデックスの代替キーと、インデックスに投影する属性を定義します。 次に、DynamoDBは、テーブルから取得したプライマリキー属性を含む、属性のコピーをインデックスに実行します。 これらのタスクを実行した後、テーブルで実行するかのようにクエリ/スキャンを使用するだけです。

DynamoDBは、すべてのセカンダリインデックスを自動的に維持します。 追加や削除などのアイテム操作では、ターゲットテーブルのインデックスが更新されます。

DynamoDBは、2種類のセカンダリインデックスを提供します-

  • グローバルセカンダリインデックス-このインデックスにはパーティションキーとソートキーが含まれますが、これらはソーステーブルとは異なる場合があります。 すべてのテーブルデータとすべてのパーティションにまたがるインデックスのクエリ/スキャン機能により、ラベル「グローバル」を使用します。
  • ローカルセカンダリインデックス-このインデックスはパーティションキーをテーブルと共有しますが、異なるソートキーを使用します。 その「ローカル」な性質は、すべてのパーティションが同一のパーティションキー値を持つテーブルパーティションにスコープされていることに起因します。

使用するインデックスの最適なタイプは、アプリケーションのニーズによって異なります。 次の表に示されている2つの違いを考慮してください-

Quality Global Secondary Index Local Secondary Index
Key Schema It uses a simple or composite primary key. It always uses a composite primary key.
Key Attributes The index partition key and sort key can consist of string, number, or binary table attributes. The partition key of the index is an attribute shared with the table partition key. The sort key can be string, number, or binary table attributes.
Size Limits Per Partition Key Value They carry no size limitations. It imposes a 10GB maximum limit on total size of indexed items associated with a partition key value.
Online Index Operations You can spawn them at table creation, add them to existing tables, or delete existing ones. You must create them at table creation, but cannot delete them or add them to existing tables.
Queries It allows queries covering the entire table, and every partition. They address single partitions through the partition key value provided in the query.
Consistency Queries of these indices only offer the eventually consistent option. Queries of these offer the options of eventually consistent or strongly consistent.
Throughput Cost It includes throughput settings for reads and writes. Queries/scans consume capacity from the index, not the table, which also applies to table write updates. Queries/scans consume table read capacity. Table writes update local indexes, and consume table capacity units.
Projection Queries/scans can only request attributes projected into the index, with no retrievals of table attributes. Queries/scans can request those attributes not projected; furthermore, automatic fetches of them occur.

セカンダリインデックスを使用して複数のテーブルを作成する場合は、順番に実行します。つまり、テーブルを作成し、ACTIVE状態になるのを待ってから、別のテーブルを作成してから再び待機します。 DynamoDBは同時作成を許可しません。

各セカンダリインデックスには特定の仕様が必要です-

  • タイプ-ローカルまたはグローバルを指定します。
  • 名前-テーブルと同じ命名規則を使用します。
  • キースキーマ-トップレベルの文字列、数値、またはバイナリタイプのみが許可され、インデックスタイプが他の要件を決定します。
  • 投影の属性-DynamoDBは自動的に投影し、任意のデータ型を許可します。
  • スループット-グローバルセカンダリインデックスの読み取り/書き込み容量を指定します。

インデックスの制限は、テーブルごとに5つのグローバルと5つのローカルのままです。

*DescribeTable* を使用して、インデックスに関する詳細情報にアクセスできます。 名前、サイズ、アイテム数を返します。

_ -これらの値は6時間ごとに更新されます。_

インデックスデータへのアクセスに使用されるクエリまたはスキャンで、テーブル名とインデックス名、結果に必要な属性、および条件ステートメントを指定します。 DynamoDBは、結果を昇順または降順で返すオプションを提供します。

_ -テーブルを削除すると、すべてのインデックスも削除されます。_

DynamoDB-グローバルセカンダリインデックス

さまざまな属性を持つさまざまなクエリタイプを必要とするアプリケーションは、これらの詳細なクエリを実行する際に単一または複数のグローバルセカンダリインデックスを使用できます。

-ユーザー、ログイン状態、ログイン時間を追跡するシステム。 前の例の成長により、そのデータに対するクエリが遅くなります。

グローバルセカンダリインデックスは、テーブルから選択した属性を整理することでクエリを高速化します。 データの並べ替えに主キーを使用し、キーテーブル属性やテーブルと同じキースキーマを必要としません。

すべてのグローバルセカンダリインデックスには、ソートキーのオプションを備えたパーティションキーが含まれている必要があります。 インデックスキースキーマはテーブルと異なる場合があり、インデックスキー属性はトップレベルの文字列、数値、またはバイナリテーブル属性を使用できます。

プロジェクションでは、他のテーブル属性を使用できますが、クエリは親テーブルから取得しません。

属性の投影

プロジェクションは、テーブルからセカンダリインデックスにコピーされた属性セットで構成されます。 プロジェクションは常にテーブルパーティションキーとソートキーで発生します。 クエリでは、プロジェクションにより、DynamoDBがプロジェクションの任意の属性にアクセスできます。基本的に、独自のテーブルとして存在します。

セカンダリインデックスの作成では、投影の属性を指定する必要があります。 DynamoDBは、このタスクを実行する3つの方法を提供します-

  • KEYS_ONLY -すべてのインデックスアイテムは、テーブルパーティションとソートキー値、インデックスキー値で構成されます。 これにより、最小のインデックスが作成されます。
  • INCLUDE -KEYS_ONLY属性と指定された非キー属性が含まれます。
  • ALL -すべてのソーステーブル属性が含まれ、可能な限り最大のインデックスが作成されます。

属性をグローバルセカンダリインデックスに投影する際のトレードオフに注意してください。これは、スループットとストレージコストに関連しています。

次の点を考慮してください-

  • いくつかの属性へのアクセスのみが必要で、待ち時間が短い場合は、必要な属性のみを投影してください。 これにより、ストレージと書き込みのコストが削減されます。
  • アプリケーションが特定の非キー属性に頻繁にアクセスする場合は、スキャン消費と比較してストレージコストが少ないため、それらを投影します。
  • 頻繁にアクセスされる属性の大きなセットを投影できますが、これには高いストレージコストがかかります。
  • まれなテーブルクエリと頻繁な書き込み/更新にはKEYS_ONLYを使用します。 これはサイズを制御しますが、それでもクエリのパフォーマンスは良好です。

グローバルセカンダリインデックスのクエリとスキャン

クエリを利用して、インデックス内の単一または複数のアイテムにアクセスできます。 インデックスとテーブル名、目的の属性、および条件を指定する必要があります。結果を昇順または降順で返すオプションがあります。

スキャンを利用して、すべてのインデックスデータを取得することもできます。 テーブルとインデックス名が必要です。 フィルタ式を利用して、特定のデータを取得します。

テーブルとインデックスのデータ同期

DynamoDBは、親テーブルとのインデックスの同期を自動的に実行します。 アイテムの変更操作ごとに非同期更新が発生しますが、アプリケーションはインデックスに直接書き込みません。

DynamoDBのメンテナンスがインデックスに与える影響を理解する必要があります。 インデックスの作成時に、キー属性とデータ型を指定します。つまり、書き込み時には、これらのデータ型はキースキーマデータ型と一致する必要があります。

アイテムの作成または削除では、インデックスは最終的に一貫した方法で更新されますが、データの更新はほんの数秒で伝播します(何らかのタイプのシステム障害が発生しない限り)。 アプリケーションのこの遅延を考慮する必要があります。

グローバルセカンダリインデックスのスループットに関する考慮事項-複数のグローバルセカンダリインデックスはスループットに影響します。 インデックスの作成には、テーブルとは別に存在するキャパシティユニット仕様が必要です。その結果、テーブルユニットではなくインデックスキャパシティユニットを消費する操作が発生します。

これにより、クエリまたは書き込みがプロビジョニングされたスループットを超える場合にスロットルが発生する可能性があります。 DescribeTable を使用してスループット設定を表示します。

読み取り容量-グローバルセカンダリインデックスは、結果整合性を提供します。 クエリでは、DynamoDBはテーブルに使用されるものと同一のプロビジョニング計算を実行しますが、アイテムサイズではなくインデックスエントリサイズを使用するという唯一の違いがあります。 クエリリターンの制限は1MBのままです。これには、返されるすべてのアイテムの属性名のサイズと値が含まれます。

書き込み容量

書き込み操作が発生すると、影響を受けるインデックスは書き込み単位を消費します。 書き込みスループットコストは、テーブル書き込みで消費される書き込み容量ユニットとインデックス更新で消費されるユニットの合計です。 書き込み操作を成功させるには、十分な容量が必要です。そうしないと、スロットルが発生します。

書き込みコストも特定の要因に依存したままであり、そのいくつかは次のとおりです-

  • インデックス付き属性を定義する新しいアイテムまたは未定義のインデックス付き属性を定義するアイテムの更新では、単一の書き込み操作を使用してアイテムをインデックスに追加します。
  • インデックス付きキー属性値を変更する更新では、2つの書き込みを使用してアイテムを削除し、新しいアイテムを書き込みます。
  • インデックス付き属性の削除をトリガーするテーブル書き込みは、単一の書き込みを使用して、インデックス内の古いアイテムの投影を消去します。
  • 更新操作の前後にインデックスに存在しないアイテムは書き込みを使用しません。
  • インデックスキースキーマの投影属性値のみを変更し、インデックスキー属性値を変更しない更新は、1回の書き込みを使用して、投影属性の値をインデックスに更新します。

これらすべての要因は、アイテムサイズが1KB以下であることを前提としています。

グローバルセカンダリインデックスストレージ

アイテムの書き込み時に、DynamoDBは属性が存在する必要があるインデックスに適切な属性セットを自動的にコピーします。 これは、テーブルアイテムのストレージと属性のストレージに課金することにより、アカウントに影響します。 使用されるスペースは、これらの量の合計から得られます-

  • テーブルの主キーのバイトサイズ
  • インデックスキー属性のバイトサイズ
  • 投影された属性のバイトサイズ
  • インデックスアイテムごとに100バイトのオーバーヘッド

平均アイテムサイズを推定し、グローバルセカンダリインデックスキー属性を使用してテーブルアイテムの数量を乗算することにより、ストレージのニーズを推定できます。

DynamoDBは、インデックスパーティションまたはソートキーとして定義された未定義の属性を持つテーブルアイテムのアイテムデータを書き込みません。

グローバルセカンダリインデックス

*CreateTable* 操作と *GlobalSecondaryIndexes* パラメーターを組み合わせて使用​​して、グローバルセカンダリインデックスを持つテーブルを作成します。 インデックスパーティションキーとして機能する属性を指定するか、インデックスソートキーに別の属性を使用する必要があります。 すべてのインデックスキー属性は、文字列、数値、またはバイナリスカラーでなければなりません。 また、 *ReadCapacityUnits* および *WriteCapacityUnits* で構成されるスループット設定を提供する必要があります。
*UpdateTable* を使用して、GlobalSecondaryIndexesパラメーターをもう一度使用して、既存のテーブルにグローバルセカンダリインデックスを追加します。

この操作では、次の入力を提供する必要があります-

  • インデックス名
  • キースキーマ
  • 投影された属性 *スループット設定

グローバルセカンダリインデックスを追加すると、アイテムボリューム、予測される属性ボリューム、書き込み容量、および書き込みアクティビティのために、大きなテーブルではかなりの時間がかかる場合があります。* CloudWatch *メトリックを使用して、プロセスを監視します。

*DescribeTable* を使用して、グローバルセカンダリインデックスのステータス情報を取得します。 GlobalSecondaryIndexesの4つの *IndexStatus* の1つを返します-
  • CREATING -インデックスの構築段階とその利用不能を示します。
  • ACTIVE -使用するインデックスの準備ができていることを示します。
  • UPDATING -スループット設定の更新ステータスを示します。
  • DELETING -インデックスの削除ステータス、およびその永久的な使用不能を示します。

ロード/バックフィルステージ中にグローバルセカンダリインデックスプロビジョニングスループット設定を更新します(DynamoDBがインデックスに属性を書き込み、追加/削除/更新されたアイテムを追跡します)。 この操作を実行するには、 UpdateTable を使用します。

バックフィルの段階では、他のインデックスを追加/削除できないことに注意してください。

UpdateTableを使用して、グローバルセカンダリインデックスを削除します。 操作ごとに1つのインデックスのみを削除できますが、最大5つまでの複数の操作を同時に実行できます。 削除プロセスは親テーブルの読み取り/書き込みアクティビティには影響しませんが、操作が完了するまで他のインデックスを追加/削除することはできません。

Javaを使用してグローバルセカンダリインデックスを操作する

CreateTableを使用してインデックス付きのテーブルを作成します。 DynamoDBクラスインスタンス、リクエスト情報用の CreateTableRequest クラスインスタンスを作成し、リクエストオブジェクトをCreateTableメソッドに渡すだけです。

次のプログラムは短い例です-

DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient (
   new ProfileCredentialsProvider()));

//Attributes
ArrayList<AttributeDefinition> attributeDefinitions = new
   ArrayList<AttributeDefinition>();
attributeDefinitions.add(new AttributeDefinition()
   .withAttributeName("City")
   .withAttributeType("S"));

attributeDefinitions.add(new AttributeDefinition()
   .withAttributeName("Date")
   .withAttributeType("S"));

attributeDefinitions.add(new AttributeDefinition()
   .withAttributeName("Wind")
   .withAttributeType("N"));

//Key schema of the table
ArrayList<KeySchemaElement> tableKeySchema = new ArrayList<KeySchemaElement>();
tableKeySchema.add(new KeySchemaElement()
   .withAttributeName("City")
   .withKeyType(KeyType.HASH));             //Partition key

tableKeySchema.add(new KeySchemaElement()
   .withAttributeName("Date")
   .withKeyType(KeyType.RANGE));            //Sort key

//Wind index
GlobalSecondaryIndex windIndex = new GlobalSecondaryIndex()
   .withIndexName("WindIndex")
   .withProvisionedThroughput(new ProvisionedThroughput()
   .withReadCapacityUnits((long) 10)
   .withWriteCapacityUnits((long) 1))
   .withProjection(new Projection().withProjectionType(ProjectionType.ALL));

ArrayList<KeySchemaElement> indexKeySchema = new ArrayList<KeySchemaElement>();
indexKeySchema.add(new KeySchemaElement()
   .withAttributeName("Date")
   .withKeyType(KeyType.HASH));             //Partition key

indexKeySchema.add(new KeySchemaElement()
   .withAttributeName("Wind")
   .withKeyType(KeyType.RANGE));            //Sort key

windIndex.setKeySchema(indexKeySchema);
CreateTableRequest createTableRequest = new CreateTableRequest()
   .withTableName("ClimateInfo")
   .withProvisionedThroughput(new ProvisionedThroughput()
   .withReadCapacityUnits((long) 5)
   .withWriteCapacityUnits((long) 1))
   .withAttributeDefinitions(attributeDefinitions)
   .withKeySchema(tableKeySchema)
   .withGlobalSecondaryIndexes(windIndex);
Table table = dynamoDB.createTable(createTableRequest);
System.out.println(table.getDescription());
*DescribeTable* を使用してインデックス情報を取得します。 最初に、DynamoDBクラスのインスタンスを作成します。 次に、インデックスを対象とするTableクラスインスタンスを作成します。 最後に、テーブルをdescribeメソッドに渡します。

ここに短い例があります-

DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient (
   new ProfileCredentialsProvider()));

Table table = dynamoDB.getTable("ClimateInfo");
TableDescription tableDesc = table.describe();
Iterator<GlobalSecondaryIndexDescription> gsiIter =
   tableDesc.getGlobalSecondaryIndexes().iterator();

while (gsiIter.hasNext()) {
   GlobalSecondaryIndexDescription gsiDesc = gsiIter.next();
   System.out.println("Index data " + gsiDesc.getIndexName() + ":");
   Iterator<KeySchemaElement> kse7Iter = gsiDesc.getKeySchema().iterator();

   while (kseIter.hasNext()) {
      KeySchemaElement kse = kseIter.next();
      System.out.printf("\t%s: %s\n", kse.getAttributeName(), kse.getKeyType());
   }
   Projection projection = gsiDesc.getProjection();
   System.out.println("\tProjection type: " + projection.getProjectionType());

   if (projection.getProjectionType().toString().equals("INCLUDE")) {
      System.out.println("\t\tNon-key projected attributes: "
         + projection.getNonKeyAttributes());
   }
}

Queryを使用して、テーブルクエリと同様にインデックスクエリを実行します。 DynamoDBクラスインスタンス、ターゲットインデックスのTableクラスインスタンス、特定のインデックスのIndexクラスインスタンスを作成し、インデックスとクエリオブジェクトをクエリメソッドに渡すだけです。

よりよく理解するために、次のコードを見てください-

DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient (
   new ProfileCredentialsProvider()));

Table table = dynamoDB.getTable("ClimateInfo");
Index index = table.getIndex("WindIndex");
QuerySpec spec = new QuerySpec()
   .withKeyConditionExpression("#d = :v_date and Wind = :v_wind")
   .withNameMap(new NameMap()
   .with("#d", "Date"))
   .withValueMap(new ValueMap()
   .withString(":v_date","2016-05-15")
   .withNumber(":v_wind",0));

ItemCollection<QueryOutcome> items = index.query(spec);
Iterator<Item> iter = items.iterator();

while (iter.hasNext()) {
   System.out.println(iter.next().toJSONPretty());
}

次のプログラムは、より良い理解のための大きな例です-

-次のプログラムは、以前に作成されたデータソースを想定している場合があります。 実行を試みる前に、サポートライブラリを取得し、必要なデータソース(必要な特性を備えたテーブル、または他の参照ソース)を作成します。

この例では、Eclipse IDE、AWS認証情報ファイル、およびEclipse AWS Javaプロジェクト内のAWS Toolkitも使用します。

import java.util.ArrayList;
import java.util.Iterator;

import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient;
import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.Index;
import com.amazonaws.services.dynamodbv2.document.Item;
import com.amazonaws.services.dynamodbv2.document.ItemCollection;
import com.amazonaws.services.dynamodbv2.document.QueryOutcome;
import com.amazonaws.services.dynamodbv2.document.Table;
import com.amazonaws.services.dynamodbv2.document.spec.QuerySpec;
import com.amazonaws.services.dynamodbv2.document.utils.ValueMap;

import com.amazonaws.services.dynamodbv2.model.AttributeDefinition;
import com.amazonaws.services.dynamodbv2.model.CreateTableRequest;
import com.amazonaws.services.dynamodbv2.model.GlobalSecondaryIndex;
import com.amazonaws.services.dynamodbv2.model.KeySchemaElement;
import com.amazonaws.services.dynamodbv2.model.KeyType;
import com.amazonaws.services.dynamodbv2.model.Projection;
import com.amazonaws.services.dynamodbv2.model.ProvisionedThroughput;

public class GlobalSecondaryIndexSample {
   static DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient (
      new ProfileCredentialsProvider()));
   public static String tableName = "Bugs";
   public static void main(String[] args) throws Exception {
      createTable();
      queryIndex("CreationDateIndex");
      queryIndex("NameIndex");
      queryIndex("DueDateIndex");
   }
   public static void createTable() {
     //Attributes
      ArrayList<AttributeDefinition> attributeDefinitions = new
         ArrayList<AttributeDefinition>();
      attributeDefinitions.add(new AttributeDefinition()
         .withAttributeName("BugID")
         .withAttributeType("S"));

      attributeDefinitions.add(new AttributeDefinition()
         .withAttributeName("Name")
         .withAttributeType("S"));

      attributeDefinitions.add(new AttributeDefinition()
         .withAttributeName("CreationDate")
         .withAttributeType("S"));

      attributeDefinitions.add(new AttributeDefinition()
         .withAttributeName("DueDate")
         .withAttributeType("S"));

     //Table Key schema
      ArrayList<KeySchemaElement> tableKeySchema = new ArrayList<KeySchemaElement>();
      tableKeySchema.add (new KeySchemaElement()
         .withAttributeName("BugID")
         .withKeyType(KeyType.HASH));             //Partition key

      tableKeySchema.add (new KeySchemaElement()
         .withAttributeName("Name")
         .withKeyType(KeyType.RANGE));            //Sort key

     //Indexes' initial provisioned throughput
      ProvisionedThroughput ptIndex = new ProvisionedThroughput()
         .withReadCapacityUnits(1L)
         .withWriteCapacityUnits(1L);

     //CreationDateIndex
      GlobalSecondaryIndex creationDateIndex = new GlobalSecondaryIndex()
         .withIndexName("CreationDateIndex")
         .withProvisionedThroughput(ptIndex)
         .withKeySchema(new KeySchemaElement()
         .withAttributeName("CreationDate")
         .withKeyType(KeyType.HASH),              //Partition key
         new KeySchemaElement()
         .withAttributeName("BugID")
         .withKeyType(KeyType.RANGE))             //Sort key
         .withProjection(new Projection()
         .withProjectionType("INCLUDE")
         .withNonKeyAttributes("Description", "Status"));

     //NameIndex
      GlobalSecondaryIndex nameIndex = new GlobalSecondaryIndex()
         .withIndexName("NameIndex")
         .withProvisionedThroughput(ptIndex)
         .withKeySchema(new KeySchemaElement()
         .withAttributeName("Name")
         .withKeyType(KeyType.HASH),                 //Partition key
         new KeySchemaElement()
         .withAttributeName("BugID")
         .withKeyType(KeyType.RANGE))                //Sort key
         .withProjection(new Projection()
         .withProjectionType("KEYS_ONLY"));

     //DueDateIndex
      GlobalSecondaryIndex dueDateIndex = new GlobalSecondaryIndex()
         .withIndexName("DueDateIndex")
         .withProvisionedThroughput(ptIndex)
         .withKeySchema(new KeySchemaElement()
         .withAttributeName("DueDate")
         .withKeyType(KeyType.HASH))              //Partition key
         .withProjection(new Projection()
         .withProjectionType("ALL"));

      CreateTableRequest createTableRequest = new CreateTableRequest()
         .withTableName(tableName)
         .withProvisionedThroughput( new ProvisionedThroughput()
         .withReadCapacityUnits( (long) 1)
         .withWriteCapacityUnits( (long) 1))
         .withAttributeDefinitions(attributeDefinitions)
         .withKeySchema(tableKeySchema)
         .withGlobalSecondaryIndexes(creationDateIndex, nameIndex, dueDateIndex);
         System.out.println("Creating " + tableName + "...");
         dynamoDB.createTable(createTableRequest);

     //Pause for active table state
      System.out.println("Waiting for ACTIVE state of " + tableName);
      try {
         Table table = dynamoDB.getTable(tableName);
         table.waitForActive();
      } catch (InterruptedException e) {
         e.printStackTrace();
      }
   }
   public static void queryIndex(String indexName) {
      Table table = dynamoDB.getTable(tableName);
      System.out.println
      ("\n*****************************************************\n");
      System.out.print("Querying index " + indexName + "...");
      Index index = table.getIndex(indexName);
      ItemCollection<QueryOutcome> items = null;
      QuerySpec querySpec = new QuerySpec();

      if (indexName == "CreationDateIndex") {
         System.out.println("Issues filed on 2016-05-22");
         querySpec.withKeyConditionExpression("CreationDate = :v_date and begins_with
            (BugID, :v_bug)")
            .withValueMap(new ValueMap()
            .withString(":v_date","2016-05-22")
            .withString(":v_bug","A-"));
         items = index.query(querySpec);
      } else if (indexName == "NameIndex") {
         System.out.println("Compile error");
         querySpec.withKeyConditionExpression("Name = :v_name and begins_with
            (BugID, :v_bug)")
            .withValueMap(new ValueMap()
            .withString(":v_name","Compile error")
            .withString(":v_bug","A-"));
         items = index.query(querySpec);
      } else if (indexName == "DueDateIndex") {
         System.out.println("Items due on 2016-10-15");
         querySpec.withKeyConditionExpression("DueDate = :v_date")
         .withValueMap(new ValueMap()
         .withString(":v_date","2016-10-15"));
         items = index.query(querySpec);
      } else {
         System.out.println("\nInvalid index name");
         return;
      }
      Iterator<Item> iterator = items.iterator();
      System.out.println("Query: getting result...");

      while (iterator.hasNext()) {
         System.out.println(iterator.next().toJSONPretty());
      }
   }
}

DynamoDB-ローカルセカンダリインデックス

一部のアプリケーションは主キーを使用してクエリを実行するだけですが、状況によっては代替ソートキーの恩恵を受ける場合があります。 単一または複数のローカルセカンダリインデックスを作成して、アプリケーションに選択を許可します。

何百万ものアイテムを組み合わせるなどの複雑なデータアクセス要件により、より効率的なクエリ/スキャンを実行する必要があります。 ローカルセカンダリインデックスは、パーティションキー値の代替ソートキーを提供します。 また、すべてまたは一部のテーブル属性のコピーも保持します。 テーブルパーティションキーでデータを整理しますが、異なるソートキーを使用します。

ローカルセカンダリインデックスを使用すると、テーブル全体をスキャンする必要がなくなり、ソートキーを使用した簡単で迅速なクエリが可能になります。

すべてのローカルセカンダリインデックスは、特定の条件を満たす必要があります-

  • 同一のパーティションキーとソーステーブルパーティションキー。
  • 1つのスカラー属性のみのソートキー。
  • 非キー属性として機能するソーステーブルのソートキーの投影。

すべてのローカルセカンダリインデックスは、親テーブルのパーティションキーとソートキーを自動的に保持します。 クエリでは、これは、投影された属性の効率的な収集と、投影されていない属性の取得を意味します。

ローカルセカンダリインデックスのストレージ制限は、パーティションキー値ごとに10 GBのままです。これには、すべてのテーブルアイテムと、パーティションキー値を共有するインデックスアイテムが含まれます。

属性を投影する

一部の操作では、複雑さのために過剰な読み取り/フェッチが必要になります。 これらの操作はかなりのスループットを消費する可能性があります。 プロジェクションを使用すると、これらの属性を分離することで、コストのかかるフェッチを避け、豊富なクエリを実行できます。 プロジェクションは、セカンダリインデックスにコピーされた属性で構成されていることに注意してください。

セカンダリインデックスを作成するときに、投影される属性を指定します。 DynamoDBが提供する3つのオプションを思い出してください: KEYS_ONLY、INCLUDE、およびALL

投影で特定の属性を選択する場合、関連するコストのトレードオフを考慮してください-

  • 必要な属性の小さなセットのみを投影すると、ストレージコストを劇的に削減できます。
  • 頻繁にアクセスされる非キー属性を投影する場合、スキャンコストとストレージコストを相殺します。
  • ほとんどまたはすべての非キー属性を投影する場合、これにより柔軟性が最大になり、スループットが低下します(取得なし)。ただし、ストレージコストは上昇します。
  • 頻繁な書き込み/更新およびまれなクエリに対してKEYS_ONLYを予測すると、サイズは最小になりますが、クエリの準備は維持されます。

ローカルセカンダリインデックスの作成

CreateTableの LocalSecondaryIndex パラメーターを使用して、単一または複数のローカルセカンダリインデックスを作成します。 ソートキーに1つの非キー属性を指定する必要があります。 テーブルの作成時に、ローカルのセカンダリインデックスを作成します。 削除時に、これらのインデックスを削除します。

ローカルセカンダリインデックスを持つテーブルは、パーティションキー値ごとにサイズが10GBの制限に従う必要がありますが、任意の量のアイテムを格納できます。

ローカルセカンダリインデックスのクエリとスキャン

ローカルセカンダリインデックスでのクエリ操作は、インデックス内の複数のアイテムがソートキー値を共有している場合、一致するパーティションキー値を持つすべてのアイテムを返します。 一致するアイテムは特定の順序で返されません。 ローカルセカンダリインデックスのクエリでは、結果整合性または強力な整合性が使用され、強力な整合性のある読み取りによって最新の値が提供されます。

スキャン操作は、すべてのローカルセカンダリインデックスデータを返します。 スキャンでは、テーブル名とインデックス名を指定し、フィルター式を使用してデータを破棄できるようにする必要があります。

アイテムライティング

ローカルセカンダリインデックスの作成時に、ソートキー属性とそのデータ型を指定します。 アイテムを記述するとき、そのアイテムがインデックスキーの属性を定義している場合、そのタイプはキースキーマのデータタイプと一致する必要があります。

DynamoDBは、テーブルアイテムとローカルセカンダリインデックスアイテムに1対1の関係要件を課しません。 複数のローカルセカンダリインデックスを持つテーブルは、少ないテーブルよりも書き込みコストが高くなります。

ローカルセカンダリインデックスのスループットに関する考慮事項

クエリの読み取り容量の消費は、データアクセスの性質によって異なります。 クエリは、結果整合性のある読み取りの半分のユニットと比較して、1つのユニットを使用した強い整合性のある読み取りで、結果整合性または強力な整合性を使用します。

結果の制限には、最大1MBのサイズが含まれます。 結果のサイズは、一致するインデックスアイテムサイズの合計を最も近い4KBに切り上げ、一致するテーブルアイテムのサイズも最も近い4KBに切り上げます。

書き込み容量の消費量は、プロビジョニングされたユニット内に残ります。 テーブル書き込みで消費されたユニットとインデックス更新で消費されたユニットの合計を見つけることにより、プロビジョニングされた総コストを計算します。

また、コストに影響を与える重要な要因を考慮することができます。

  • インデックス付き属性を定義するアイテムを作成するか、アイテムを更新して未定義のインデックス付き属性を定義すると、単一の書き込み操作が発生します。
  • テーブルの更新によってインデックス付きキー属性値が変更されると、2つの書き込みが発生して削除され、次にアイテムが追加されます。
  • 書き込みによってインデックス付き属性が削除されると、1回の書き込みが発生して古いアイテムの投影が削除されます。
  • 更新前または更新後にアイテムがインデックス内に存在しない場合、書き込みは発生しません。

ローカルセカンダリインデックスストレージ

テーブル項目の書き込み時に、DynamoDBは適切な属性セットを必要なローカルセカンダリインデックスに自動的にコピーします。 これによりアカウントに課金されます。 使用されるスペースは、テーブルのプライマリキーのバイトサイズ、インデックスキーの属性バイトサイズ、現在の投影された属性のバイトサイズ、および各インデックス項目のオーバーヘッドの100バイトの合計から生じます。

推定ストレージは、インデックスアイテムの平均サイズを推定し、テーブルアイテムの数量で乗算することによって取得されます。

Javaを使用してローカルセカンダリインデックスを操作する

最初にDynamoDBクラスインスタンスを作成して、ローカルセカンダリインデックスを作成します。 次に、必要な要求情報を使用してCreateTableRequestクラスインスタンスを作成します。 最後に、createTableメソッドを使用します。

DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient(
   new ProfileCredentialsProvider()));
String tableName = "Tools";
CreateTableRequest createTableRequest = new
   CreateTableRequest().withTableName(tableName);

//Provisioned Throughput
createTableRequest.setProvisionedThroughput (
   new ProvisionedThroughput()
   .withReadCapacityUnits((long)5)
   .withWriteCapacityUnits(( long)5));

//Attributes
ArrayList<AttributeDefinition> attributeDefinitions =
   new ArrayList<AttributeDefinition>();
   attributeDefinitions.add(new AttributeDefinition()
   .withAttributeName("Make")
   .withAttributeType("S"));

attributeDefinitions.add(new AttributeDefinition()
   .withAttributeName("Model")
   .withAttributeType("S"));

attributeDefinitions.add(new AttributeDefinition()
   .withAttributeName("Line")
   .withAttributeType("S"));

createTableRequest.setAttributeDefinitions(attributeDefinitions);

//Key Schema
ArrayList<KeySchemaElement> tableKeySchema = new
   ArrayList<KeySchemaElement>();

tableKeySchema.add(new KeySchemaElement()
   .withAttributeName("Make")
   .withKeyType(KeyType.HASH));                   //Partition key

tableKeySchema.add(new KeySchemaElement()
   .withAttributeName("Model")
   .withKeyType(KeyType.RANGE));                  //Sort key

createTableRequest.setKeySchema(tableKeySchema);
ArrayList<KeySchemaElement> indexKeySchema = new
   ArrayList<KeySchemaElement>();

indexKeySchema.add(new KeySchemaElement()
   .withAttributeName("Make")
   .withKeyType(KeyType.HASH));                  //Partition key

indexKeySchema.add(new KeySchemaElement()
   .withAttributeName("Line")
   .withKeyType(KeyType.RANGE));                  //Sort key

Projection projection = new Projection()
   .withProjectionType(ProjectionType.INCLUDE);

ArrayList<String> nonKeyAttributes = new ArrayList<String>();
nonKeyAttributes.add("Type");
nonKeyAttributes.add("Year");
projection.setNonKeyAttributes(nonKeyAttributes);

LocalSecondaryIndex localSecondaryIndex = new LocalSecondaryIndex()
   .withIndexName("ModelIndex")
   .withKeySchema(indexKeySchema)
   .withProjection(p rojection);

ArrayList<LocalSecondaryIndex> localSecondaryIndexes = new
   ArrayList<LocalSecondaryIndex>();

localSecondaryIndexes.add(localSecondaryIndex);
createTableRequest.setLocalSecondaryIndexes(localSecondaryIndexes);
Table table = dynamoDB.createTable(createTableRequest);
System.out.println(table.getDescription());

describeメソッドを使用して、ローカルのセカンダリインデックスに関する情報を取得します。 DynamoDBクラスインスタンスを作成し、Tableクラスインスタンスを作成して、テーブルをdescribeメソッドに渡すだけです。

DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient(
   new ProfileCredentialsProvider()));

String tableName = "Tools";
Table table = dynamoDB.getTable(tableName);
TableDescription tableDescription = table.describe();

List<LocalSecondaryIndexDescription> localSecondaryIndexes =
   tableDescription.getLocalSecondaryIndexes();

Iterator<LocalSecondaryIndexDescription> lsiIter =
   localSecondaryIndexes.iterator();

while (lsiIter.hasNext()) {
   LocalSecondaryIndexDescription lsiDescription = lsiIter.next();
   System.out.println("Index info " + lsiDescription.getIndexName() + ":");
   Iterator<KeySchemaElement> kseIter = lsiDescription.getKeySchema().iterator();

   while (kseIter.hasNext()) {
      KeySchemaElement kse = kseIter.next();
      System.out.printf("\t%s: %s\n", kse.getAttributeName(), kse.getKeyType());
   }

   Projection projection = lsiDescription.getProjection();
   System.out.println("\tProjection type: " + projection.getProjectionType());

   if (projection.getProjectionType().toString().equals("INCLUDE")) {
      System.out.println("\t\tNon-key projected attributes: " +
         projection.getNonKeyAttributes());
   }
}

テーブルクエリと同じ手順を使用してクエリを実行します。 DynamoDBクラスインスタンス、Tableクラスインスタンス、Indexクラスインスタンス、クエリオブジェクトを作成し、クエリメソッドを利用します。

DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient(
   new ProfileCredentialsProvider()));

String tableName = "Tools";
Table table = dynamoDB.getTable(tableName);
Index index = table.getIndex("LineIndex");
QuerySpec spec = new QuerySpec()
   .withKeyConditionExpression("Make = :v_make and Line = :v_line")
   .withValueMap(new ValueMap()
   .withString(":v_make", "Depault")
   .withString(":v_line", "SuperSawz"));

ItemCollection<QueryOutcome> items = index.query(spec);
Iterator<Item> itemsIter = items.iterator();

while (itemsIter.hasNext()) {
   Item item = itemsIter.next();
   System.out.println(item.toJSONPretty());
}

次の例を確認することもできます。

-次の例では、以前に作成されたデータソースを想定しています。 実行を試みる前に、サポートライブラリを取得し、必要なデータソース(必要な特性を備えたテーブル、または他の参照ソース)を作成します。

次の例では、Eclipse IDE、AWS認証情報ファイル、およびEclipse AWS Javaプロジェクト内のAWS Toolkitも使用しています。

import java.util.ArrayList;
import java.util.Iterator;

import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient;

import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.Index;
import com.amazonaws.services.dynamodbv2.document.Item;
import com.amazonaws.services.dynamodbv2.document.ItemCollection;
import com.amazonaws.services.dynamodbv2.document.PutItemOutcome;
import com.amazonaws.services.dynamodbv2.document.QueryOutcome;
import com.amazonaws.services.dynamodbv2.document.Table;
import com.amazonaws.services.dynamodbv2.document.spec.QuerySpec;
import com.amazonaws.services.dynamodbv2.document.utils.ValueMap;

import com.amazonaws.services.dynamodbv2.model.AttributeDefinition;
import com.amazonaws.services.dynamodbv2.model.CreateTableRequest;
import com.amazonaws.services.dynamodbv2.model.KeySchemaElement;
import com.amazonaws.services.dynamodbv2.model.KeyType;
import com.amazonaws.services.dynamodbv2.model.LocalSecondaryIndex;
import com.amazonaws.services.dynamodbv2.model.Projection;
import com.amazonaws.services.dynamodbv2.model.ProjectionType;
import com.amazonaws.services.dynamodbv2.model.ProvisionedThroughput;
import com.amazonaws.services.dynamodbv2.model.ReturnConsumedCapacity;
import com.amazonaws.services.dynamodbv2.model.Select;

public class LocalSecondaryIndexSample {
   static DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient(
      new ProfileCredentialsProvider()));
   public static String tableName = "ProductOrders";

   public static void main(String[] args) throws Exception {
      createTable();
      query(null);
      query("IsOpenIndex");
      query("OrderCreationDateIndex");
   }
   public static void createTable() {
      CreateTableRequest createTableRequest = new CreateTableRequest()
         .withTableName(tableName)
         .withProvisionedThroughput(new ProvisionedThroughput()
         .withReadCapacityUnits((long) 1)
         .withWriteCapacityUnits((long) 1));

     //Table partition and sort keys attributes
      ArrayList<AttributeDefinition> attributeDefinitions = new
         ArrayList<AttributeDefinition>();

      attributeDefinitions.add(new AttributeDefinition()
         .withAttributeName("CustomerID")
         .withAttributeType("S"));

      attributeDefinitions.add(new AttributeDefinition()
         .withAttributeName("OrderID")
         .withAttributeType("N"));

     //Index primary key attributes
      attributeDefinitions.add(new AttributeDefinition()
         .withAttributeName("OrderDate")
         .withAttributeType("N"));

      attributeDefinitions.add(new AttributeDefinition()
         .withAttributeName("OpenStatus")
         .withAttributeType("N"));
      createTableRequest.setAttributeDefinitions(attributeDefinitions);

     //Table key schema
      ArrayList<KeySchemaElement> tableKeySchema = new
         ArrayList<KeySchemaElement>();
      tableKeySchema.add(new KeySchemaElement()
         .withAttributeName("CustomerID")
         .withKeyType(KeyType.HASH));                   //Partition key

      tableKeySchema.add(new KeySchemaElement()
         .withAttributeName("OrderID")
         .withKeyType(KeyType.RANGE));                  //Sort key

      createTableRequest.setKeySchema(tableKeySchema);
      ArrayList<LocalSecondaryIndex> localSecondaryIndexes = new
         ArrayList<LocalSecondaryIndex>();

     //OrderDateIndex
      LocalSecondaryIndex orderDateIndex = new LocalSecondaryIndex()
         .withIndexName("OrderDateIndex");

     //OrderDateIndex key schema
      ArrayList<KeySchemaElement> indexKeySchema = new
         ArrayList<KeySchemaElement>();
      indexKeySchema.add(new KeySchemaElement()
         .withAttributeName("CustomerID")
         .withKeyType(KeyType.HASH));                  //Partition key

      indexKeySchema.add(new KeySchemaElement()
         .withAttributeName("OrderDate")
         .withKeyType(KeyType.RANGE));                  //Sort key
      orderDateIndex.setKeySchema(indexKeySchema);

     //OrderCreationDateIndex projection w/attributes list
      Projection projection = new Projection()
         .withProjectionType(ProjectionType.INCLUDE);

      ArrayList<String> nonKeyAttributes = new ArrayList<String>();
      nonKeyAttributes.add("ProdCat");
      nonKeyAttributes.add("ProdNomenclature");
      projection.setNonKeyAttributes(nonKeyAttributes);
      orderCreationDateIndex.setProjection(projection);
      localSecondaryIndexes.add(orderDateIndex);

     //IsOpenIndex
      LocalSecondaryIndex isOpenIndex = new LocalSecondaryIndex()
         .withIndexName("IsOpenIndex");

     //OpenStatusIndex key schema
      indexKeySchema = new ArrayList<KeySchemaElement>();
      indexKeySchema.add(new KeySchemaElement()
         .withAttributeName("CustomerID")
         .withKeyType(KeyType.HASH));                  //Partition key

      indexKeySchema.add(new KeySchemaElement()
         .withAttributeName("OpenStatus")
         .withKeyType(KeyType.RANGE));                  //Sort key

     //OpenStatusIndex projection
      projection = new Projection() .withProjectionType(ProjectionType.ALL);
      OpenStatusIndex.setKeySchema(indexKeySchema);
      OpenStatusIndex.setProjection(projection);
      localSecondaryIndexes.add(OpenStatusIndex);

     //Put definitions in CreateTable request
      createTableRequest.setLocalSecondaryIndexes(localSecondaryIndexes);
      System.out.println("Spawning table " + tableName + "...");
      System.out.println(dynamoDB.createTable(createTableRequest));

     //Pause for ACTIVE status
      System.out.println("Waiting for ACTIVE table:" + tableName);
      try {
         Table table = dynamoDB.getTable(tableName);
         table.waitForActive();
      } catch (InterruptedException e) {
         e.printStackTrace();
      }
   }
   public static void query(String indexName) {
      Table table = dynamoDB.getTable(tableName);
      System.out.println("\n*************************************************\n");
      System.out.println("Executing query on" + tableName);
      QuerySpec querySpec = new QuerySpec()
         .withConsistentRead(true)
         .withScanIndexForward(true)
         .withReturnConsumedCapacity(ReturnConsumedCapacity.TOTAL);

      if (indexName == "OpenStatusIndex") {
         System.out.println("\nEmploying index: '" + indexName
            + "' open orders for this customer.");

         System.out.println(
            "Returns only user-specified attribute list\n");
         Index index = table.getIndex(indexName);

         querySpec.withKeyConditionExpression("CustomerID = :v_custmid and
            OpenStatus = :v_openstat")
            .withValueMap(new ValueMap()
            .withString(":v_custmid", "[email protected]")
            .withNumber(":v_openstat", 1));

         querySpec.withProjectionExpression(
            "OrderDate, ProdCat, ProdNomenclature, OrderStatus");
            ItemCollection<QueryOutcome> items = index.query(querySpec);
            Iterator<Item> iterator = items.iterator();
            System.out.println("Printing query results...");

         while (iterator.hasNext()) {
            System.out.println(iterator.next().toJSONPretty());
         }
      } else if (indexName == "OrderDateIndex") {
         System.out.println("\nUsing index: '" + indexName
            + "': this customer's orders placed after 05/22/2016.");
         System.out.println("Projected attributes are returned\n");
         Index index = table.getIndex(indexName);

         querySpec.withKeyConditionExpression("CustomerID = :v_custmid and OrderDate
            >= :v_ordrdate")
            .withValueMap(new ValueMap()
            .withString(":v_custmid", "[email protected]")
            .withNumber(":v_ordrdate", 20160522));

         querySpec.withSelect(Select.ALL_PROJECTED_ATTRIBUTES);
         ItemCollection<QueryOutcome> items = index.query(querySpec);
         Iterator<Item> iterator = items.iterator();
         System.out.println("Printing query results...");

         while (iterator.hasNext()) {
            System.out.println(iterator.next().toJSONPretty());
         }
      } else {
         System.out.println("\nNo index: All Jane's orders by OrderID:\n");
         querySpec.withKeyConditionExpression("CustomerID = :v_custmid")
            .withValueMap(new ValueMap()
            .withString(":v_custmid", "[email protected]"));

         ItemCollection<QueryOutcome> items = table.query(querySpec);
         Iterator<Item> iterator = items.iterator();
         System.out.println("Printing query results...");

         while (iterator.hasNext()) {
            System.out.println(iterator.next().toJSONPretty());
         }
      }
   }
}

DynamoDB-集約

DynamoDBは集約関数を提供しません。 これらのタスクを実行するには、クエリ、スキャン、インデックス、および各種ツールを創造的に使用する必要があります。 これらすべてにおいて、これらの操作でのクエリ/スキャンのスループット費用は重い場合があります。

また、好みのDynamoDBコーディング言語にライブラリやその他のツールを使用するオプションもあります。 DynamoDBを使用する前に、DynamoDBとの互換性を確認してください。

最大または最小の計算

結果の昇順/降順の保存順序、Limitパラメーター、および最高値と最低値を見つけるための順序を設定するパラメーターを利用します。

たとえば-

Map<String, AttributeValue> eaval = new HashMap<>();
eaval.put(":v1", new AttributeValue().withS("hashval"));
queryExpression = new DynamoDBQueryExpression<Table>()
   .withIndexName("yourindexname")
   .withKeyConditionExpression("HK = :v1")
   .withExpressionAttributeValues(values)
   .withScanIndexForward(false);               //descending order

queryExpression.setLimit(1);
QueryResultPage<Lookup> res =
   dynamoDBMapper.queryPage(Table.class, queryExpression);

カウントを計算する

*DescribeTable* を使用してテーブルアイテムの数を取得しますが、古いデータを提供することに注意してください。 また、Java * getScannedCountメソッド*を利用します。
*LastEvaluatedKey* を使用して、すべての結果を確実に配信します。

たとえば-

ScanRequest scanRequest = new ScanRequest().withTableName(yourtblName);
ScanResult yourresult = client.scan(scanRequest);
System.out.println("#items:" + yourresult.getScannedCount());

平均と合計の計算

インデックスとクエリ/スキャンを使用して、処理する前に値を取得およびフィルタリングします。 次に、オブジェクトを通じてこれらの値を操作します。

DynamoDB-アクセス制御

DynamoDBは、リクエストを認証するために提供された資格情報を使用します。 これらの認証情報は必須であり、AWSリソースアクセスのアクセス許可を含める必要があります。 これらの権限は、DynamoDBのほぼすべての側面から、操作または機能のマイナーな機能にまで及びます。

許可の種類

このセクションでは、DynamoDBのさまざまな権限とリソースアクセスについて説明します。

ユーザーの認証

サインアップ時に、ルート資格情報として機能するパスワードと電子メールを提供しました。 DynamoDBはこのデータをAWSアカウントに関連付け、それを使用してすべてのリソースへの完全なアクセスを提供します。

AWSでは、管理アカウントの作成にのみルート認証情報を使用することをお勧めします。 これにより、より少ない権限でIAMアカウント/ユーザーを作成できます。 IAMユーザーは、IAMサービスで生成される他のアカウントです。 アクセス許可/特権には、セキュリティで保護されたページへのアクセスや、テーブルの変更などの特定のカスタム許可が含まれます。

アクセスキーは、追加のアカウントとアクセスのための別のオプションを提供します。 これらを使用してアクセスを許可し、特定の状況でのアクセスの手動許可を回避します。 フェデレーションユーザーは、IDプロバイダーを介したアクセスを許可することにより、さらに別のオプションを提供します。

管理

AWSリソースはアカウントの所有権のままです。 許可ポリシーは、リソースの生成またはアクセスに付与される許可を管理します。 管理者は、アクセス許可ポリシーをIAM ID、つまりロール、グループ、ユーザー、サービスに関連付けます。 また、リソースにアクセス許可を付加します。

許可は、ユーザー、リソース、およびアクションを指定します。 管理者は、単に管理者特権を持つアカウントであることに注意してください。

操作とリソース

テーブルは引き続きDynamoDBの主要なリソースです。 サブリソースは、追加のリソース(ストリームやインデックスなど)として機能します。 これらのリソースは一意の名前を使用し、その一部は次の表に記載されています-

Type ARN (Amazon Resource Name)
Stream arn:aws:dynamodb:region:account-id:table/table-name/stream/stream-label
Index arn:aws:dynamodb:region:account-id:table/table-name/index/index-name
Table arn:aws:dynamodb:region:account-id:table/table-name

所有権

リソース所有者は、リソースを生成したAWSアカウント、またはリソース作成時のリクエスト認証を担当するプリンシパルエンティティアカウントとして定義されます。 これがDynamoDB環境内でどのように機能するかを検討してください-

  • ルート資格情報を使用してテーブルを作成する場合、アカウントはリソース所有者のままです。
  • IAMユーザーを作成し、ユーザーにテーブルを作成するアクセス許可を付与する際、アカウントはリソース所有者のままです。
  • IAMユーザーを作成し、ユーザー、およびロールを引き受けることができるユーザー、テーブルを作成する権限を付与する際、アカウントはリソース所有者のままです。

リソースアクセスの管理

アクセスの管理では、主にユーザーとリソースアクセスを説明するアクセス許可ポリシーに注意する必要があります。 ポリシーをIAM IDまたはリソースに関連付けます。 ただし、DynamoDBはIAM/IDポリシーのみをサポートします。

アイデンティティベース(IAM)ポリシーを使用すると、次の方法で特権を付与できます-

  • ユーザーまたはグループにアクセス許可を添付します。
  • クロスアカウント権限のロールに権限を添付します。

他のAWSでは、リソースベースのポリシーが許可されています。 これらのポリシーは、S3バケットなどへのアクセスを許可します。

ポリシー要素

ポリシーは、アクション、効果、リソース、およびプリンシパルを定義します。これらの操作を実行する権限を付与します。

-API操作には、複数のアクションのアクセス許可が必要な場合があります。

次のポリシー要素を詳しく見てください-

  • リソース-ARNはこれを識別します。
  • アクション-これらのリソース操作、および許可するか拒否するかを識別するキーワード。
  • 効果-アクションに対するユーザーリクエストの効果を指定します。これは、拒否をデフォルトとして許可または拒否を意味します。
  • プリンシパル-これは、ポリシーに関連付けられているユーザーを識別します。

条件

権限を付与する際に、特定の日付など、ポリシーがアクティブになるタイミングの条件を指定できます。 AWSシステム全体のキーとDynamoDBキーを含む条件キーで条件を表現します。 これらのキーについては、チュートリアルの後半で詳しく説明します。

コンソールのアクセス許可

ユーザーがコンソールを使用するには、特定の基本的な権限が必要です。 また、他の標準サービスのコンソールの権限も必要です-

  • CloudWatch
  • データパイプライン
  • アイデンティティおよびアクセス管理
  • 通知サービス
  • ラムダ

IAMポリシーの制限が強すぎる場合、ユーザーはコンソールを効果的に使用できません。 また、CLIまたはAPIを呼び出すだけのユーザーのアクセス許可について心配する必要はありません。

一般的な使用Iamポリシー

AWSは、スタンドアロンIAM管理ポリシーを使用したアクセス許可の一般的な操作をカバーしています。 これらは重要な権限を提供するため、付与する必要のあるものに対する深い調査を避けることができます。

それらのいくつかは次のとおりです-

  • AmazonDynamoDBReadOnlyAccess -コンソール経由で読み取り専用アクセスを提供します。
  • AmazonDynamoDBFullAccess -コンソールを介したフルアクセスを提供します。
  • AmazonDynamoDBFullAccesswithDataPipeline -コンソールを介したフルアクセスを提供し、Data Pipelineによるエクスポート/インポートを許可します。

もちろん、カスタムポリシーを作成することもできます。

特権の付与:シェルの使用

Javascriptシェルを使用して許可を付与できます。 次のプログラムは、典型的な許可ポリシーを示しています-

{
   "Version": "2016-05-22",
   "Statement": [
      {
         "Sid": "DescribeQueryScanToolsTable",
         "Effect": "Deny",

         "Action": [
            "dynamodb:DescribeTable",
            "dynamodb:Query",
            "dynamodb:Scan"
         ],
         "Resource": "arn:aws:dynamodb:us-west-2:account-id:table/Tools"
      }
   ]
}

次の3つの例を確認できます-

ユーザーによるテーブルアクションの実行をブロックします。

{
   "Version": "2016-05-23",
   "Statement": [
      {
         "Sid": "AllAPIActionsOnTools",
         "Effect": "Deny",
         "Action": "dynamodb:*",
         "Resource": "arn:aws:dynamodb:us-west-2:155556789012:table/Tools"
      }
   ]
}

テーブルとそのインデックスへのアクセスをブロックします。

{
   "Version": "2016-05-23",
   "Statement": [
      {
         "Sid": "AccessAllIndexesOnTools",
         "Effect": "Deny",
         "Action": [
            "dynamodb:*"
         ],
         "Resource": [
            "arn:aws:dynamodb:us-west-2:155556789012:table/Tools",
            "arn:aws:dynamodb:us-west-2:155556789012:table/Tools/index/*"
         ]
      }
   ]
}
  • ユーザーがリザーブドキャパシティーオファリングを購入できないようにします
{
   "Version": "2016-05-23",
   "Statement": [
      {
         "Sid": "BlockReservedCapacityPurchases",
         "Effect": "Deny",
         "Action": "dynamodb:PurchaseReservedCapacityOfferings",
         "Resource": "arn:aws:dynamodb:us-west-2:155556789012:*"
      }
   ]
}

特権の付与:GUIコンソールの使用

GUIコンソールを使用してIAMポリシーを作成することもできます。 まず、ナビゲーションペインから[テーブル]を選択します。 テーブルリストで、ターゲットテーブルを選択し、次の手順に従います。

  • ステップ1 *-*アクセス制御*タブを選択します。

ステップ2 *-IDプロバイダー、アクション、およびポリシー属性を選択します。 すべての設定を入力した後、 *Create policy を選択します。

  • ステップ3 *-*ポリシー指示の添付*を選択し、必要な各ステップを完了して、ポリシーを適切なIAMロールに関連付けます。

DynamoDB-Permissions API

DynamoDB APIは、アクセス許可を必要とする多数のアクションセットを提供します。 許可を設定するには、許可されるアクション、許可されるリソース、およびそれぞれの条件を確立する必要があります。

ポリシーの[アクション]フィールド内でアクションを指定できます。 ポリシーの[リソース]フィールド内でリソース値を指定します。 ただし、API操作ではDynamodb:プレフィックスを含む正しい構文を使用するようにしてください。

例- dynamodb:CreateTable

条件キーを使用して権限をフィルタリングすることもできます。

権限とAPIアクション

次の表に記載されているAPIアクションと関連する権限をよく見てください-

API Operation Necessary Permission
BatchGetItem dynamodb:BatchGetItem
BatchWriteItem dynamodb:BatchWriteItem
CreateTable dynamodb:CreateTable
DeleteItem dynamodb:DeleteItem
DeleteTable dynamodb:DeleteTable
DescribeLimits dynamodb:DescribeLimits
DescribeReservedCapacity dynamodb:DescribeReservedCapacity
DescribeReservedCapacityOfferings dynamodb:DescribeReservedCapacityOfferings
DescribeStream dynamodb:DescribeStream
DescribeTable dynamodb:DescribeTable
GetItem dynamodb:GetItem
GetRecords dynamodb:GetRecords
GetShardIterator dynamodb:GetShardIterator
ListStreams dynamodb:ListStreams
ListTables dynamodb:ListTables
PurchaseReservedCapacityOfferings dynamodb:PurchaseReservedCapacityOfferings
PutItem dynamodb:PutItem
Query dynamodb:Query
Scan dynamodb:Scan
UpdateItem dynamodb:UpdateItem
UpdateTable dynamodb:UpdateTable

リソース

次の表では、許可された各APIアクションに関連付けられたリソースを確認できます-

API Operation Resource
BatchGetItem arn:aws:dynamodb:region:account-id:table/table-name
BatchWriteItem arn:aws:dynamodb:region:account-id:table/table-name
CreateTable arn:aws:dynamodb:region:account-id:table/table-name
DeleteItem arn:aws:dynamodb:region:account-id:table/table-name
DeleteTable arn:aws:dynamodb:region:account-id:table/table-name
DescribeLimits arn:aws:dynamodb:region:account-id:*
DescribeReservedCapacity arn:aws:dynamodb:region:account-id:*
DescribeReservedCapacityOfferings arn:aws:dynamodb:region:account-id:*
DescribeStream arn:aws:dynamodb:region:account-id:table/table-name/stream/stream-label
DescribeTable arn:aws:dynamodb:region:account-id:table/table-name
GetItem arn:aws:dynamodb:region:account-id:table/table-name
GetRecords arn:aws:dynamodb:region:account-id:table/table-name/stream/stream-label
GetShardIterator arn:aws:dynamodb:region:account-id:table/table-name/stream/stream-label
ListStreams arn:aws:dynamodb:region:account-id:table/table-name/stream/*
ListTables *
PurchaseReservedCapacityOfferings arn:aws:dynamodb:region:account-id:*
PutItem arn:aws:dynamodb:region:account-id:table/table-name
Query

arn:aws:dynamodb:region:account-id:table/table-name

or

arn:aws:dynamodb:region:account-id:table/table-name/index/index-name

Scan

arn:aws:dynamodb:region:account-id:table/table-name

or

arn:aws:dynamodb:region:account-id:table/table-name/index/index-name

UpdateItem arn:aws:dynamodb:region:account-id:table/table-name
UpdateTable arn:aws:dynamodb:region:account-id:table/table-name

DynamoDB-条件

権限を付与する際、DynamoDBでは、条件キーを使用した詳細なIAMポリシーを介して権限を指定できます。 これは、特定のアイテムや属性へのアクセスなどの設定をサポートします。

注意-DynamoDBはタグをサポートしていません。

詳細な制御

いくつかの条件では、ユーザーアカウントに基づいて特定のアイテムへの読み取り専用アクセスを許可するなど、アイテムおよび属性を特定できます。 セキュリティ資格情報を管理する条件付きIAMポリシーを使用して、このレベルの制御を実装します。 次に、目的のユーザー、グループ、およびロールにポリシーを適用します。 後述するトピックであるWeb Identity Federationは、Amazon、Facebook、およびGoogleのログインを介したユーザーアクセスを制御する方法も提供します。

IAMポリシーの条件要素は、アクセス制御を実装します。 ポリシーに追加するだけです。 その使用例は、テーブル項目と属性へのアクセスを拒否または許可することです。 条件要素は、条件キーを使用して権限を制限することもできます。

条件キーの次の2つの例を確認できます-

  • dynamodb:LeadingKeys -パー​​ティションキーの値と一致するIDを持たないユーザーによるアイテムアクセスを防ぎます。
  • dynamodb:Attributes -ユーザーがリストされている属性以外の属性にアクセスしたり操作したりできないようにします。

評価では、IAMポリシーは真または偽の値になります。 いずれかの部分が偽と評価された場合、ポリシー全体が偽と評価され、アクセスが拒否されます。 ユーザーが適切にアクセスできるように、条件キーに必要な情報をすべて指定してください。

定義済みの条件キー

AWSは、すべてのサービスに適用される事前定義された条件キーのコレクションを提供します。 これらは、ユーザーとアクセスの調査において幅広い用途と詳細をサポートします。

注意-条件キーには大文字と小文字の区別があります。

次のサービス固有のキーの選択を確認できます-

  • dynamodb:LeadingKey -テーブルの最初のキー属性を表します。パーティションキー。 条件でForAllValues修飾子を使用します。
  • dynamodb:Select -クエリ/スキャンリクエストのSelectパラメーターを表します。 値はALL_ATTRIBUTES、ALL_PROJECTED_ATTRIBUTES、SPECIFIC_ATTRIBUTES、またはCOUNTでなければなりません。
  • dynamodb:Attributes -リクエスト内の属性名リスト、またはリクエストから返された属性を表します。 その値とその機能は、APIアクションパラメーターに似ています。たとえば、BatchGetItemはAttributesToGetを使用します。
  • dynamodb:ReturnValues -リクエストのReturnValuesパラメーターを表し、ALL_OLD、UPDATED_OLD、ALL_NEW、UPDATED_NEW、NONEの値を使用できます。
  • dynamodb:ReturnConsumedCapacity -要求のReturnConsumedCapacityパラメーターを表し、TOTALおよびNONEの値を使用できます。

DynamoDB-Web Identity Federation

Web Identity Federationを使用すると、大規模なユーザーグループの認証と承認を簡素化できます。 個々のアカウントの作成をスキップし、ユーザーにIDプロバイダーへのログインを要求して、一時的な資格情報またはトークンを取得することができます。 AWS Security Token Service(STS)を使用して認証情報を管理します。 アプリケーションはこれらのトークンを使用してサービスと対話します。

Web Identity Federationは、Amazon、Google、Facebookなどの他のIDプロバイダーもサポートしています。

機能-使用中、Web Identity Federationはユーザーとアプリの認証のために最初にIDプロバイダーを呼び出し、プロバイダーはトークンを返します。 これにより、アプリはAWS STSを呼び出し、入力用のトークンを渡します。 STSはアプリを承認し、一時的なアクセス認証情報を付与します。これにより、アプリはIAMロールを使用し、ポリシーに基づいてリソースにアクセスできます。

Web Identity Federationの実装

あなたは使用する前に次の3つのステップを実行する必要があります-

  • サポートされているサードパーティのIDプロバイダーを使用して、開発者として登録します。
  • アプリケーションをプロバイダーに登録して、アプリIDを取得します。
  • ポリシーの添付を含む、単一または複数のIAMロールを作成します。 アプリごとにプロバイダーごとにロールを使用する必要があります。

IAMロールの1つがWeb Identity Federationを使用すると仮定します。 その後、アプリは3段階のプロセスを実行する必要があります-

  • 認証
  • 資格情報の取得
  • リソースアクセス

最初のステップでは、アプリは独自のインターフェイスを使用してプロバイダーを呼び出し、トークンプロセスを管理します。

次に、ステップ2はトークンを管理し、アプリが AssumeRoleWithWebIdentity リクエストをAWS STSに送信することを要求します。 リクエストは、最初のトークン、プロバイダーアプリID、およびIAMロールのARNを保持します。 STSは、一定期間後に期限切れになるように設定された資格情報を提供します。

最後のステップで、アプリはDynamoDBリソースのアクセス情報を含む応答をSTSから受け取ります。 アクセス資格情報、有効期限、ロール、ロールIDで構成されます。

DynamoDB-データパイプライン

Data Pipelineでは、テーブル、ファイル、またはS3バケットとの間でデータをエクスポートおよびインポートできます。 もちろん、これはバックアップ、テスト、および同様のニーズやシナリオで役立ちます。

エクスポートでは、データパイプラインコンソールを使用します。これは、新しいパイプラインを作成し、Amazon EMR(Elastic MapReduce)クラスターを起動してエクスポートを実行します。 EMRはDynamoDBからデータを読み取り、ターゲットに書き込みます。 このチュートリアルの後半で、EMRについて詳しく説明します。

インポート操作では、データパイプラインコンソールを使用して、パイプラインを作成し、EMRを起動してインポートを実行します。 ソースからデータを読み取り、宛先に書き込みます。

_ -使用されるサービス、具体的にはEMRとS3の場合、エクスポート/インポート操作にはコストがかかります。

データパイプラインの使用

データパイプラインを使用するときは、アクションとリソースのアクセス許可を指定する必要があります。 IAMロールまたはポリシーを使用してそれらを定義できます。 インポート/エクスポートを実行しているユーザーは、アクティブなアクセスキーIDとシークレットキーが必要になることに注意してください。

データパイプラインのIAMロール

データパイプラインを使用するには、2つのIAMロールが必要です-

  • DataPipelineDefaultRole -これには、パイプラインに実行を許可するすべてのアクションがあります。
  • DataPipelineDefaultResourceRole -これには、パイプラインがプロビジョニングを許可するリソースがあります。

Data Pipelineを初めて使用する場合は、各ロールを作成する必要があります。 既存のロールにより、以前のユーザーはすべてこれらのロールを所有しています。

IAMコンソールを使用してデータパイプラインのIAMロールを作成し、次の4つのステップを実行します-

  • ステップ2 *-ダッシュボードから*役割*を選択します。

ステップ3 *-*新しいロールの作成*を選択します。 次に、[ロール名]フィールドにDataPipelineDefaultRoleと入力し、[次のステップ]を選択します。 *Role Type パネルの AWS Service Roles リストで、 Data Pipeline に移動し、 Select を選択します。 Review パネルで Create Role を選択します。

  • ステップ4 *-*新しいロールの作成*を選択します。

DynamoDB-データバックアップ

Data Pipelineのインポート/エクスポート機能を使用して、バックアップを実行します。 バックアップの実行方法は、GUIコンソールを使用するか、Data Pipelineを直接使用するか(API)によって異なります。 コンソールを使用する場合はテーブルごとに個別のパイプラインを作成するか、直接オプションを使用する場合は単一のパイプラインで複数のテーブルをインポート/エクスポートします。

データのエクスポートとインポート

エクスポートを実行する前に、Amazon S3バケットを作成する必要があります。 1つ以上のテーブルからエクスポートできます。

エクスポートを実行するには、次の4つのステップのプロセスを実行します-

ステップ2 *-使用するAWSリージョンにパイプラインがない場合は、 *Get started now を選択します。 1つ以上ある場合は、[新しいパイプラインを作成]を選択します。

  • ステップ3 *-作成ページで、パイプラインの名前を入力します。 [ソース]パラメーターに[テンプレートを使用してビルド]を選択します。 リストから[DynamoDBテーブルをS3にエクスポート] *を選択します。 * Source DynamoDBテーブル名*フィールドにソーステーブルを入力します。

s3://nameOfBucket/region/nameOfFolderの形式を使用して、 Output S3 Folder テキストボックスに宛先S3バケットを入力します。 S3 location for logs テキストボックスに、ログファイルのS3宛先を入力します。

ステップ4 *-すべての設定を入力した後、 *Activate を選択します。

パイプラインが作成プロセスを完了するまでに数分かかる場合があります。 コンソールを使用して、そのステータスを監視します。 エクスポートされたファイルを表示して、S3コンソールで処理が成功したことを確認します。

データのインポート

インポートが成功するのは、宛先テーブルを作成し、宛先とソースが同じ名前を使用し、宛先とソースが同じキースキーマを使用する場合のみです。

移入された宛先テーブルを使用できますが、インポートはキーを共有するデータアイテムをソースアイテムに置き換え、余分なアイテムをテーブルに追加します。 宛先は別のリージョンを使用することもできます。

複数のソースをエクスポートできますが、操作ごとにインポートできるのは1つだけです。 あなたは、次の手順に従うことでインポートを実行することができます-

  • ステップ1 *-AWSマネジメントコンソールにログインし、データパイプラインコンソールを開きます。
  • ステップ2 *-クロスリージョンインポートを実行する場合は、宛先リージョンを選択する必要があります。
  • ステップ3 *-*新しいパイプラインの作成*を選択します。
  • ステップ4 *-*名前*フィールドにパイプライン名を入力します。 [ソース]パラメーターに[テンプレートを使用してビルドする]を選択し、テンプレートリストで[S3からDynamoDBバックアップデータをインポートする]を選択します。

[入力S3フォルダー]テキストボックスにソースファイルの場所を入力します。 [ターゲットDynamoDBテーブル名]フィールドに宛先テーブル名を入力します。 次に、 S3 location for logs テキストボックスにログファイルの場所を入力します。

ステップ5 *-すべての設定を入力した後、 *Activate を選択します。

インポートは、パイプラインの作成後すぐに開始されます。 パイプラインが作成プロセスを完了するまでに数分かかる場合があります。

エラー

エラーが発生すると、データパイプラインコンソールはパイプラインステータスとしてERRORを表示します。 エラーのあるパイプラインをクリックすると、詳細ページが表示され、プロセスのすべてのステップと障害が発生したポイントが表示されます。 内部のログファイルも洞察を提供します。

次のように、エラーの一般的な原因を確認できます-

  • インポートの宛先テーブルが存在しないか、ソースと同一のキースキーマを使用していません。
  • S3バケットが存在しないか、ユーザーに読み取り/書き込み権限がありません。
  • パイプラインがタイムアウトしました。
  • 必要なエクスポート/インポート権限がありません。
  • AWSアカウントがリソース制限に達しました。

DynamoDB-モニタリング

Amazonは、CloudWatchコンソール、コマンドライン、またはCloudWatch APIを介してパフォーマンスを集約および分析するCloudWatchを提供しています。 また、これを使用してアラームを設定し、タスクを実行することもできます。 特定のイベントに対して指定されたアクションを実行します。

Cloudwatchコンソール

管理コンソールにアクセスしてCloudWatchを使用し、https://console.aws.amazon.com/cloudwatch/でCloudWatchコンソールを開きます。

その後、次の手順を実行できます-

  • ナビゲーションペインから[ Metrics ]を選択します。
  • CloudWatch Metrics by Category ペイン内のDynamoDBメトリックスで、 Table Metrics を選択します。 上部ペインを使用して下にスクロールし、テーブルメトリックのリスト全体を確認します。 表示*リストには、メトリックオプションがあります。

結果インターフェイスでは、リソース名とメトリックの横にあるチェックボックスを選択することにより、各メトリックを選択/選択解除できます。 次に、各アイテムのグラフを表示できます。

API統合

クエリを使用してCloudWatchにアクセスできます。 メトリック値を使用して、CloudWatchアクションを実行します。 Note DynamoDBは、値がゼロのメトリックを送信しません。 それらのメトリックがその値のままである期間のメトリックを単にスキップします。

以下は、最も一般的に使用されるメトリックの一部です-

  • ConditionalCheckFailedRequests -条件付きPutItem書き込みなどの条件付き書き込みの試行失敗回数を追跡します。 失敗した書き込みは、評価がfalseになると、このメトリックを1つ増やします。 また、HTTP 400エラーもスローします。
  • ConsumedReadCapacityUnits -特定の期間に使用された容量単位を定量化します。 これを使用して、個々のテーブルとインデックスの消費を調べることができます。
  • ConsumedWriteCapacityUnits -特定の期間に使用された容量単位を定量化します。 これを使用して、個々のテーブルとインデックスの消費を調べることができます。
  • ReadThrottleEvents -テーブル/インデックスの読み取りで、プロビジョニングされた容量単位を超えるリクエストを定量化します。 複数のスロットルを持つバッチ操作を含む各スロットルで増加します。
  • ReturnedBytes -特定の期間内の取得操作で返されたバイトを定量化します。
  • ReturnedItemCount -一定期間のクエリおよびスキャン操作で返されるアイテムを定量化します。 評価されたアイテムではなく、返されたアイテムのみに対応します。これらは通常、まったく異なる数字です。

_ -さらに多くのメトリックが存在し、これらのほとんどにより、平均、合計、最大、最小、およびカウントを計算できます。

DynamoDB-CloudTrail

DynamoDBにはCloudTrail統合が含まれています。 アカウント内のDynamoDBとの間の低レベルAPIリクエストをキャプチャし、指定されたS3バケットにログファイルを送信します。 コンソールまたはAPIからの呼び出しを対象としています。 このデータを使用して、行われたリクエストとそのソース、ユーザー、タイムスタンプなどを判断できます。

有効にすると、他のサービスレコードを含むログファイルでアクションを追跡します。 8つのアクションと2つのストリームをサポートしています-

8つのアクションは次のとおりです-

  • CreateTable
  • DeleteTable
  • DescribeTable
  • ListTables
  • UpdateTable
  • DescribeReservedCapacity
  • DescribeReservedCapacityOfferings
  • PurchaseReservedCapacityOfferings

一方、2つのストリームは-

  • DescribeStream
  • ListStreams

すべてのログには、リクエストを行っているアカウントに関する情報が含まれています。 ルートまたはIAMユーザーがリクエストを行ったかどうか、一時的な認証情報を使用しているかフェデレーションを使用しているかなどの詳細情報を確認できます。

ログファイルは、アーカイブと削除の設定により、指定した期間だけストレージに残ります。 デフォルトでは、暗号化されたログが作成されます。 新しいログのアラートを設定できます。 また、リージョンやアカウントをまたいで、複数のログを単一のバケットに整理することもできます。

ログファイルの解釈

各ファイルには、単一または複数のエントリが含まれます。 各エントリは、複数のJSON形式のイベントで構成されています。 エントリはリクエストを表し、関連情報が含まれます。順序の保証なし。

次のサンプルログファイルを確認できます-

{"Records": [
   {
      "eventVersion": "5.05",
      "userIdentity": {
         "type": "AssumedRole",
         "principalId": "AKTTIOSZODNN8SAMPLE:jane",
         "arn": "arn:aws:sts::155522255533:assumed-role/users/jane",
         "accountId": "155522255533",
         "accessKeyId": "AKTTIOSZODNN8SAMPLE",

         "sessionContext": {
            "attributes": {
               "mfaAuthenticated": "false",
               "creationDate": "2016-05-11T19:01:01Z"
            },

            "sessionIssuer": {
               "type": "Role",
               "principalId": "AKTTI44ZZ6DHBSAMPLE",
               "arn": "arn:aws:iam::499955777666:role/admin-role",
               "accountId": "499955777666",
               "userName": "jill"
            }
         }
      },

      "eventTime": "2016-05-11T14:33:20Z",
      "eventSource": "dynamodb.amazonaws.com",
      "eventName": "DeleteTable",
      "awsRegion": "us-west-2",
      "sourceIPAddress": "192.0.2.0",
      "userAgent": "console.aws.amazon.com",
      "requestParameters": {"tableName": "Tools"},

      "responseElements": {"tableDescription": {
         "tableName": "Tools",
         "itemCount": 0,

         "provisionedThroughput": {
            "writeCapacityUnits": 25,
            "numberOfDecreasesToday": 0,
            "readCapacityUnits": 25
         },
         "tableStatus": "DELETING",
         "tableSizeBytes": 0
      }},
      "requestID": "4D89G7D98GF7G8A7DF78FG89AS7GFSO5AEMVJF66Q9ASUAAJG",
      "eventID": "a954451c-c2fc-4561-8aea-7a30ba1fdf52",
      "eventType": "AwsApiCall",
      "apiVersion": "2013-04-22",
      "recipientAccountId": "155522255533"
   }
]}

DynamoDB-MapReduce

AmazonのElastic MapReduce(EMR)を使用すると、ビッグデータを迅速かつ効率的に処理できます。 EMRはEC2インスタンスでApache Hadoopを実行しますが、プロセスを簡素化します。 Apache link:/hive/index [Hive]を使用して、SQLに似たクエリ言語であるlink:/hive/hiveql_select_where [HiveQL]を介したクエリマップ削減ジョブフローを使用します。 Apache Hiveは、クエリとアプリケーションを最適化する方法として機能します。

管理コンソールの[EMR]タブ、EMR CLI、API、またはSDKを使用して、ジョブフローを起動できます。 また、Hiveをインタラクティブに実行するか、スクリプトを使用するオプションもあります。

EMRの読み取り/書き込み操作はスループットの消費に影響しますが、大規模な要求では、バックオフアルゴリズムの保護により再試行を実行します。 また、EMRを他の操作およびタスクと同時に実行すると、調整が行われる場合があります。

DynamoDB/EMR統合は、バイナリおよびバイナリセットの属性をサポートしていません。

DynamoDB/EMR統合の前提条件

EMRを使用する前に、必要な項目のこのチェックリストを確認してください-

  • AWSアカウント
  • EMR操作で使用されているのと同じアカウントの下のデータが入ったテーブル
  • DynamoDB接続を備えたカスタムHiveバージョン
  • DynamoDB接続サポート
  • S3バケット(オプション)
  • SSHクライアント(オプション)
  • EC2キーペア(オプション)

ハイブのセットアップ

EMRを使用する前に、キーペアを作成して、Hiveをインタラクティブモードで実行します。 キーペアにより、ジョブフローのEC2インスタンスとマスターノードへの接続が可能になります。

次の手順に従うことでこれを実行できます-

  • 管理コンソールにログインし、https://console.aws.amazon.com/ec2/v2/home [https://console.aws.amazon.com/ec2/]にあるEC2コンソールを開きます
  • コンソールの右上部分で領域を選択します。 リージョンがDynamoDBリージョンと一致することを確認します。
  • [ナビゲーション]ペインで、[キーペア]を選択します。
  • [キーペアの作成]を選択します。
  • [キーペア名]フィールドに名前を入力し、[作成]を選択します。 *次の形式を使用して、結果の秘密鍵ファイルをダウンロードします:filename.pem。

* 注*-キーペアがないとEC2インスタンスに接続できません。

ハイブクラスター

Hiveを実行するためのHive対応クラスターを作成します。 Hive-DynamoDB接続に必要なアプリケーションおよびインフラストラクチャの環境を構築します。

次の手順を使用して、このタスクを実行できます-

  • EMRコンソールにアクセスします。
  • [ Create Cluster ]を選択します。
  • 作成画面で、クラスターのわかりやすい名前を使用してクラスター構成を設定し、終了保護に*はい*を選択し、ログに*有効*を、*ログフォルダーS3の場所にS3宛先*を、デバッグに*有効*をオンにします。 。
  • [ソフトウェアの構成]画面で、Hadoopディストリビューションの Amazon 、AMIバージョンの最新バージョン、Install-HiveのアプリケーションのデフォルトのHiveバージョン、およびインストールのアプリケーションのデフォルトのPigバージョンを保持するフィールドを確認します。
  • [ハードウェア構成]画面で、フィールドが[ネットワークのEC2-Classicで起動]、[EC2アベイラビリティゾーンの*設定なし]、マスターAmazon Amazon EC2インスタンスタイプのデフォルト、リクエストスポットインスタンスのチェックなし、コアのデフォルトを保持していることを確認します-Amazon EC2インスタンスタイプ、カウントの 2 、リクエストスポットインスタンスのチェックなし、タスク-Amazon EC2インスタンスタイプのデフォルト、カウントの 0 、リクエストスポットインスタンスのチェックなし。

クラスター障害を防ぐために十分な容量を提供する制限を設定してください。

  • [セキュリティとアクセス]画面で、フィールドにEC2キーペアのキーペア、他のIAMユーザー*はIAMユーザーアクセス、 *Proceed without roles はIAMロールに保持されていることを確認します。

  • [ブートストラップアクション]画面を確認しますが、変更しないでください。

  • 設定を確認し、終了したら Create Cluster を選択します。

    *Summary* ペインがクラスターの開始に表示されます。

SSHセッションをアクティブにする

マスターノードに接続してCLI操作を実行するには、アクティブなSSHセッションが必要です。 EMRコンソールでクラスターを選択して、マスターノードを見つけます。 マスターノードを*マスターパブリックDNS名*としてリストします。

PuTTYがない場合はインストールします。 次に、PuTTYgenを起動し、 Load を選択します。 PEMファイルを選択して開きます。 PuTTYgenは、インポートが成功したことを通知します。 秘密キーを保存*を選択してPuTTY秘密キー形式(PPK)で保存し、パスフレーズなしで保存する場合は*はい*を選択します。 次に、PuTTYキーの名前を入力し、 *Save を押して、PuTTYgenを閉じます。

最初にPuTTYを起動して、PuTTYを使用してマスターノードと接続します。 [カテゴリ]リストから[セッション]を選択します。 [ホスト名]フィールドにhadoop @ DNSと入力します。 [カテゴリ]リストで[接続]> [SSH *]を展開し、[*認証]を選択します。 制御オプション画面で、[認証用の秘密キーファイルの*参照*]を選択します。 次に、秘密鍵ファイルを選択して開きます。 セキュリティ警告ポップアップで[はい]を選択します。

マスターノードに接続すると、Hadoopコマンドプロンプトが表示されます。これは、インタラクティブなHiveセッションを開始できることを意味します。

ハイブテーブル

Hiveはデータウェアハウスツールとして機能し、link:/hive/hiveql_select_where [HiveQL]を使用してEMRクラスターでクエリを実行できます。 前のセットアップでは、作業プロンプトが表示されます。 「ハイブ」と入力し、必要なコマンドを入力するだけで、Hiveコマンドをインタラクティブに実行します。 link:/hive/index [Hive]の詳細については、Hiveチュートリアルを参照してください。

DynamoDB-テーブルアクティビティ

DynamoDBストリームを使用すると、テーブルアイテムの変更を追跡して対応できます。 この機能を使用して、ソース間で情報を更新することで変更に対応するアプリケーションを作成します。 大規模なマルチユーザーシステムの何千人ものユーザーのデータを同期します。 これを使用して、更新に関する通知をユーザーに送信します。 そのアプリケーションは、多様で実質的です。 DynamoDBストリームは、この機能を実現するために使用されるメインツールとして機能します。

ストリームは、テーブル内のアイテムの変更を含む時間順シーケンスをキャプチャします。 このデータは最大24時間保持されます。 アプリケーションはそれらを使用して、ほぼリアルタイムで元のアイテムと変更されたアイテムを表示します。

テーブルで有効なストリームは、すべての変更をキャプチャします。 CRUD操作では、DynamoDBは変更されたアイテムのプライマリキー属性を持つストリームレコードを作成します。 前後の画像などの追加情報のストリームを構成できます。

ストリームには2つの保証があります-

  • 各レコードはストリームに1回表示され、
  • 各アイテムを変更すると、変更と同じ順序のストリームレコードが生成されます。

すべてのストリームはリアルタイムで処理されるため、アプリケーションの関連機能にそれらを使用できます。

ストリームの管理

テーブルの作成時に、ストリームを有効にできます。 既存のテーブルでは、ストリームを無効にしたり、設定を変更したりできます。 ストリームは非同期操作の機能を提供するため、テーブルのパフォーマンスに影響はありません。

シンプルなストリーム管理にAWSマネジメントコンソールを利用します。 まず、コンソールに移動し、 Tables を選択します。 [概要]タブで、[ストリームの管理]を選択します。 ウィンドウ内で、テーブルデータの変更時にストリームに追加される情報を選択します。 すべての設定を入力したら、*有効*を選択します。

既存のストリームを無効にする場合は、*ストリームの管理*を選択してから、*無効*を選択します。

API CreateTableおよびUpdateTableを使用して、ストリームを有効化または変更することもできます。 パラメーターStreamSpecificationを使用して、ストリームを構成します。 StreamEnabledはステータスを指定します。つまり、有効な場合はtrue、無効な場合はfalseを意味します。

StreamViewTypeは、ストリームに追加される情報、KEYS_ONLY、NEW_IMAGE、OLD_IMAGE、およびNEW_AND_OLD_IMAGESを指定します。

ストリームリーディング

エンドポイントに接続し、APIリクエストを行うことにより、ストリームを読み取り、処理します。 各ストリームはストリームレコードで構成され、各レコードはストリームを所有する単一の変更として存在します。 ストリームレコードには、発行順序を示すシーケンス番号が含まれます。 レコードは、シャードとも呼ばれるグループに属します。 シャードは、複数のレコードのコンテナーとして機能し、レコードへのアクセスとトラバースに必要な情報も保持します。 24時間後、レコードは自動的に削除されます。

これらのシャードは、必要に応じて生成および削除され、長続きしません。 また、通常は書き込みアクティビティの急増に応じて、複数の新しいシャードに自動的に分割されます。 ストリームを無効にすると、シャードを閉じます。 シャード間の階層関係により、アプリケーションは正しい処理順序のために親シャードに優先順位を付ける必要があります。 Kinesisアダプターを使用して、これを自動的に行うことができます。

_ -変更のない操作では、ストリームレコードは書き込まれません。

レコードにアクセスして処理するには、次のタスクを実行する必要があります-

  • ターゲットストリームのARNを決定します。
  • ターゲットレコードを保持するストリームのシャードを決定します。 *シャードにアクセスして、目的のレコードを取得します。

_* 注*-シャードを一度に読み取る最大2つのプロセスが必要です。 2プロセスを超える場合、ソースを調整できます。

利用可能なストリームAPIアクションは次のとおりです。

  • ListStreams
  • DescribeStream
  • GetShardIterator
  • GetRecords

あなたは、ストリームの読み取りの次の例を確認することができます-

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBStreamsClient;

import com.amazonaws.services.dynamodbv2.model.AttributeAction;
import com.amazonaws.services.dynamodbv2.model.AttributeDefinition;
import com.amazonaws.services.dynamodbv2.model.AttributeValue;
import com.amazonaws.services.dynamodbv2.model.AttributeValueUpdate;

import com.amazonaws.services.dynamodbv2.model.CreateTableRequest;
import com.amazonaws.services.dynamodbv2.model.DescribeStreamRequest;
import com.amazonaws.services.dynamodbv2.model.DescribeStreamResult;
import com.amazonaws.services.dynamodbv2.model.DescribeTableResult;

import com.amazonaws.services.dynamodbv2.model.GetRecordsRequest;
import com.amazonaws.services.dynamodbv2.model.GetRecordsResult;
import com.amazonaws.services.dynamodbv2.model.GetShardIteratorRequest;
import com.amazonaws.services.dynamodbv2.model.GetShardIteratorResult;

import com.amazonaws.services.dynamodbv2.model.KeySchemaElement;
import com.amazonaws.services.dynamodbv2.model.KeyType;
import com.amazonaws.services.dynamodbv2.model.ProvisionedThroughput;
import com.amazonaws.services.dynamodbv2.model.Record;

import com.amazonaws.services.dynamodbv2.model.Shard;
import com.amazonaws.services.dynamodbv2.model.ShardIteratorType;
import com.amazonaws.services.dynamodbv2.model.StreamSpecification;
import com.amazonaws.services.dynamodbv2.model.StreamViewType;
import com.amazonaws.services.dynamodbv2.util.Tables;

public class StreamsExample {
   private static AmazonDynamoDBClient dynamoDBClient =
      new AmazonDynamoDBClient(new ProfileCredentialsProvider());
   private static AmazonDynamoDBStreamsClient streamsClient =
      new AmazonDynamoDBStreamsClient(new ProfileCredentialsProvider());

   public static void main(String args[]) {
      dynamoDBClient.setEndpoint("InsertDbEndpointHere");
      streamsClient.setEndpoint("InsertStreamEndpointHere");

     //table creation
      String tableName = "MyTestingTable";
      ArrayList<AttributeDefinition> attributeDefinitions =
         new ArrayList<AttributeDefinition>();

      attributeDefinitions.add(new AttributeDefinition()
         .withAttributeName("ID")
         .withAttributeType("N"));

      ArrayList<KeySchemaElement> keySchema = new
         ArrayList<KeySchemaElement>();

      keySchema.add(new KeySchemaElement()
         .withAttributeName("ID")
         .withKeyType(KeyType.HASH));                      //Partition key

      StreamSpecification streamSpecification = new StreamSpecification();
      streamSpecification.setStreamEnabled(true);
      streamSpecification.setStreamViewType(StreamViewType.NEW_AND_OLD_IMAGES);
      CreateTableRequest createTableRequest = new CreateTableRequest()
         .withTableName(tableName)
         .withKeySchema(keySchema)
         .withAttributeDefinitions(attributeDefinitions)
         .withProvisionedThroughput(new ProvisionedThroughput()
         .withReadCapacityUnits(1L)
         .withWriteCapacityUnits(1L))
         .withStreamSpecification(streamSpecification);

      System.out.println("Executing CreateTable for " + tableName);
      dynamoDBClient.createTable(createTableRequest);
      System.out.println("Creating " + tableName);

      try {
         Tables.awaitTableToBecomeActive(dynamoDBClient, tableName);
      } catch (InterruptedException e) {
         e.printStackTrace();
      }

     //Get the table's stream settings
      DescribeTableResult describeTableResult =
         dynamoDBClient.describeTable(tableName);

      String myStreamArn = describeTableResult.getTable().getLatestStreamArn();
      StreamSpecification myStreamSpec =
         describeTableResult.getTable().getStreamSpecification();

      System.out.println("Current stream ARN for " + tableName + ": "+ myStreamArn);
      System.out.println("Stream enabled: "+ myStreamSpec.getStreamEnabled());
      System.out.println("Update view type: "+ myStreamSpec.getStreamViewType());

     //Add an item
      int numChanges = 0;
      System.out.println("Making some changes to table data");
      Map<String, AttributeValue> item = new HashMap<String, AttributeValue>();
      item.put("ID", new AttributeValue().withN("222"));
      item.put("Alert", new AttributeValue().withS("item!"));
      dynamoDBClient.putItem(tableName, item);
      numChanges++;

     //Update the item
      Map<String, AttributeValue> key = new HashMap<String, AttributeValue>();
      key.put("ID", new AttributeValue().withN("222"));
      Map<String, AttributeValueUpdate> attributeUpdates =
      new HashMap<String, AttributeValueUpdate>();

      attributeUpdates.put("Alert", new AttributeValueUpdate()
         .withAction(AttributeAction.PUT)
         .withValue(new AttributeValue().withS("modified item")));

      dynamoDBClient.updateItem(tableName, key, attributeUpdates);
      numChanges++;

     //Delete the item
      dynamoDBClient.deleteItem(tableName, key);
      numChanges++;

     //Get stream shards
      DescribeStreamResult describeStreamResult =
      streamsClient.describeStream(new DescribeStreamRequest()
         .withStreamArn(myStreamArn));
      String streamArn =
         describeStreamResult.getStreamDescription().getStreamArn();
      List<Shard> shards =
         describeStreamResult.getStreamDescription().getShards();

     //Process shards
      for (Shard shard : shards) {
         String shardId = shard.getShardId();
         System.out.println("Processing " + shardId + " in "+ streamArn);

        //Get shard iterator
         GetShardIteratorRequest getShardIteratorRequest = new
            GetShardIteratorRequest()
            .withStreamArn(myStreamArn)
            .withShardId(shardId)
            .withShardIteratorType(ShardIteratorType.TRIM_HORIZON);

         GetShardIteratorResult getShardIteratorResult =
            streamsClient.getShardIterator(getShardIteratorRequest);
         String nextItr = getShardIteratorResult.getShardIterator();

         while (nextItr != null && numChanges > 0) {
           //Read data records with iterator
            GetRecordsResult getRecordsResult =
               streamsClient.getRecords(new GetRecordsRequest().
               withShardIterator(nextItr));

            List<Record> records = getRecordsResult.getRecords();
            System.out.println("Pulling records...");

            for (Record record : records) {
               System.out.println(record);
               numChanges--;
            }
            nextItr = getRecordsResult.getNextShardIterator();
         }
      }
   }
}

DynamoDB-エラー処理

リクエストの処理が失敗すると、DynamoDBはエラーをスローします。 各エラーは、HTTPステータスコード、例外名、およびメッセージのコンポーネントで構成されています。 エラー管理は、エラーを伝播するSDKまたは独自のコードに基づいています。

コードとメッセージ

例外は、さまざまなHTTPヘッダーステータスコードに分類されます。 4xxおよび5xxは、リクエストの問題とAWSに関連するエラーを保持します。

HTTP 4xxカテゴリの例外の選択は次のとおりです-

  • AccessDeniedException -クライアントがリクエストに正しく署名できませんでした。
  • ConditionalCheckFailedException -偽と評価された条件。
  • IncompleteSignatureException -要求に不完全な署名が含まれていました。

HTTP 5xxカテゴリの例外は次のとおりです-

  • 内部サーバーエラー
  • サービスは利用できません

再試行とバックオフアルゴリズム

エラーは、サーバー、スイッチ、ロードバランサー、その他の構造やシステムなど、さまざまなソースから発生します。 一般的なソリューションは、信頼性をサポートする単純な再試行で構成されます。 すべてのSDKにはこのロジックが自動的に含まれており、アプリケーションのニーズに合わせて再試行パラメーターを設定できます。

たとえば-Javaは、再試行を停止するためにmaxErrorRetry値を提供します。

Amazonは、フローを制御するために、再試行に加えてバックオフソリューションを使用することをお勧めします。 これは、再試行間の待機期間を徐々に増やし、最終的にはかなり短い期間後に停止することで構成されます。 注SDKは自動再試行を実行しますが、指数バックオフは実行しません。

次のプログラムは、リトライバックオフの例です-

public enum Results {
   SUCCESS,
   NOT_READY,
   THROTTLED,
   SERVER_ERROR
}
public static void DoAndWaitExample() {
   try {
     //asynchronous operation.
      long token = asyncOperation();
      int retries = 0;
      boolean retry = false;

      do {
         long waitTime = Math.min(getWaitTime(retries), MAX_WAIT_INTERVAL);
         System.out.print(waitTime + "\n");

        //Pause for result
         Thread.sleep(waitTime);

        //Get result
         Results result = getAsyncOperationResult(token);

         if (Results.SUCCESS == result) {
            retry = false;
         } else if (Results.NOT_READY == result) {
            retry = true;
         } else if (Results.THROTTLED == result) {
            retry = true;
         } else if (Results.SERVER_ERROR == result) {
            retry = true;
         } else {

           //stop on other error
            retry = false;
         }
      } while (retry && (retries++ < MAX_RETRIES));
   }
   catch (Exception ex) {
   }
}
public static long getWaitTime(int retryCount) {
   long waitTime = ((long) Math.pow(3, retryCount) * 100L);
   return waitTime;
}

DynamoDB-ベストプラクティス

特定のプラクティスでは、さまざまなソースや要素を操作するときにコードを最適化し、エラーを防ぎ、スループットコストを最小限に抑えます。

以下は、DynamoDBで最も重要で一般的に使用されるベストプラクティスの一部です。

テーブル

テーブルの分散は、読み取り/書き込みアクティビティをすべてのテーブルアイテムに均等に分散する最適なアプローチを意味します。

テーブルアイテムへの均一なデータアクセスを目指します。 最適なスループットの使用は、主キーの選択とアイテムのワークロードパターンに基づいています。 ワークロードをパーティションキー値全体に均等に分散します。 少量の頻繁に使用されるパーティションキー値などを避けます。 大量の個別のパーティションキー値など、より適切な選択肢を選択します。

パーティションの動作を理解します。 DynamoDBによって自動的に割り当てられたパーティションを推定します。

DynamoDBはバーストスループットの使用を提供します。これにより、電力の「バースト」のために未使用のスループットが予約されます。 バーストは大量のスループットをすぐに消費するため、このオプションを頻繁に使用しないでください。さらに、信頼できるリソースであることは証明されていません。

アップロード時に、パフォーマンスを向上させるためにデータを配信します。 割り当てられたすべてのサーバーに同時にアップロードすることにより、これを実装します。

頻繁に使用されるアイテムをキャッシュして、読み取りアクティビティをデータベースではなくキャッシュにオフロードします。

アイテム

調整、パフォーマンス、サイズ、およびアクセスコストは、引き続きアイテムの最大の懸念事項です。 1対多のテーブルを選択します。 アクセスパターンに一致するように属性を削除し、テーブルを分割します。 このシンプルなアプローチにより、効率を劇的に改善できます。

大きな値を圧縮してから保存します。 標準の圧縮ツールを使用します。 S3などの大きな属性値には代替ストレージを使用します。 オブジェクトをS3に、識別子をアイテムに保存できます。

仮想アイテムを介して複数のアイテムに大きな属性を配布します。 これにより、アイテムサイズの制限に対する回避策が提供されます。

クエリとスキャン

クエリとスキャンは、主にスループット消費の課題に悩まされます。 通常、強い整合性のある読み取りへの切り替えなどの結果として生じるバーストを避けます。 リソースの少ない方法で並列スキャンを使用します(つまり、スロットルなしのバックグラウンド機能)。 さらに、それらを大きなテーブルでのみ使用し、スループットまたはスキャン操作を十分に活用していない状況では、パフォーマンスが低下します。

ローカルセカンダリインデックス

インデックスは、スループットとストレージコスト、およびクエリの効率の分野で問題を提示します。 頻繁に属性を照会しない限り、索引付けは避けてください。 予測では、インデックスが膨張するため、賢明に選択してください。 頻繁に使用されるもののみを選択してください。

スパースインデックスを使用します。これは、すべてのテーブル項目にソートキーが表示されないインデックスを意味します。 ほとんどのテーブル項目に存在しない属性のクエリに役立ちます。

アイテムコレクション(すべてのテーブルアイテムとそのインデックス)の展開に注意してください。 追加/更新操作により、テーブルとインデックスの両方が大きくなり、コレクションの制限は10GBのままです。

グローバルセカンダリインデックス

インデックスは、スループットとストレージコスト、およびクエリの効率の分野で問題を提示します。 主要な属性の分散を選択します。これは、テーブルでの読み取り/書き込みの分散のように、ワークロードの均一性を提供します。 データを均等に分散する属性を選択します。 また、スパースインデックスを利用します。

適度な量のデータを要求するクエリで高速検索を行うために、グローバルセカンダリインデックスを活用します。