share facebook facebook twitter menu hatena pocket slack

2012.01.26 THU

DynamoDBってなんじゃ?(SDK編)

三浦 悟

WRITTEN BY 三浦 悟

前回は、DynamoDBってなんじゃ?(AWSコンソール編)にて、テーブルの作成まで行いました。
今回は、それらのテーブルにSDKを利用してアクセスしてみます。
ここでは、PHP SDKを使用します。

○クラスの初期化

DynamoDBクラスの初期化は以下のように行います。
また、キー等のパラメータは認証用のファイルに記載しておき、省略することも可能です。

$ddb = new AmazonDynamoDB(
  array(
   'key' => 'xxxxxxxxxxxxxxx',
   'secret' => 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyy',
   'default_cache_config' => '/tmp/cache'));

○データの投入

前回作成した2つのテーブルにそれぞれデータを投入します。
値の指定は、DynamoDBの型名とstring値を紐付けた形で投入します。

//book
$books = array(
array('1', '978-4274066306', 'Joel on Software'),
array('2', '978-0321413093', 'Implementation Patterns'),
array('3', '978-1244865723', 'Agile Software Development'),
);
for($i=0; $i  $ddb->put_item(array(
    'TableName' => 'book',
    'Item' => array(
      'id'   => array(AmazonDynamoDB::TYPE_NUMBER => (string)$books[$i][0]),
      'isbn' => array(AmazonDynamoDB::TYPE_STRING => (string)$books[$i][1]),
      'name' => array(AmazonDynamoDB::TYPE_STRING => (string)$books[$i][2]),
     )
  ));
}

//comment
$comments = array(
  array('1', strtotime('-10 days'), 'memorycraft', 'i like this'),
  array('1', strtotime('-7 days'), 'hoge', 'i never like this'),
  array('2', strtotime('-9 days'), 'moge', 'this is awesome'),
);
for($i=0; $i  $ddb->put_item(array(
    'TableName' => 'comment',
    'Item' => array(
      'book_id'    => array(AmazonDynamoDB::TYPE_NUMBER => (string)$comments[$i][0]),
      'posted_at'  => array(AmazonDynamoDB::TYPE_NUMBER => (string)$comments[$i][1]),
      'username'   => array(AmazonDynamoDB::TYPE_STRING => (string)$comments[$i][2]),
      'message'    => array(AmazonDynamoDB::TYPE_STRING => (string)$comments[$i][3]),
    )
  ));
}

○データアクセス

先程、データを投入したテーブルに対して、値の取得を行ないます。
Hashのプライマリキーで一意に取得できる場合は、下記のようにget_itemで行います。

//Hashプライマリキーで完全一致
echo 'get_item (1) ' .
print_r(
  $ddb->get_item(
    array(
      'TableName' => 'book',
      'Key' => array('HashKeyElement' => array(AmazonDynamoDB::TYPE_NUMBER => '1')
    )
  )->body->Item->to_json(),
  true
) . "n";

出力は以下のようになります。

get_item (1) {"id":{"N":"1"},"isbn":{"S":"978-4274066306"},"name":{"S":"Joel on Software"}}

複合プライマリキーを使い、Hashキーを指定し、Rangeキーで絞るような場合は、queryを使用します。

//複合キーで検索
echo 'query ' .
print_r(
  $ddb->query(
    array('TableName' => 'comment',
      'HashKeyValue' => array(AmazonDynamoDB::TYPE_NUMBER => '1'),
      'ConsistentRead' => true,
      'RangeKeyCondition' => array(
        'ComparisonOperator' => AmazonDynamoDB::CONDITION_GREATER_THAN_OR_EQUAL,
        'AttributeValueList' => array(array(AmazonDynamoDB::TYPE_NUMBER => (string)strtotime('-8 days')))
      )
    )
  )->body->Items->to_json(),
  true
) . "n";

出力は以下のようになります。

query {"0":{"book_id":{"N":"1"},"message":{"S":"i never like this"},"posted_at":{"N":"1326880572"},"username":{"S":"hoge"}}}

また、キー値以外で検索を行う場合は、scan関数を利用します。

//キー以外で検索
echo 'scan ' .
print_r(
  $ddb->scan(
    array(
      'TableName' => 'comment',
      'AttributeToGet' => array('username', 'message'),
      'ScanFilter' => array(
        'username' => array(
          'ComparisonOperator' => AmazonDynamoDB::CONDITION_EQUAL,
          'AttributeValueList' => array(
            array(AmazonDynamoDB::TYPE_STRING => 'memorycraft')
          )
        )
      )
    )
  )->body->Items->to_json(),
  true
) . "n";

出力は以下のようになります。

scan {"0":{"book_id":{"N":"1"},"message":{"S":"i like this"},"posted_at":{"N":"1326621372"},"username":{"S":"memorycraft"}}}

○テーブルの作成

テーブルの作成は以下のように行います。

//book
$ddb->create_table(array(
        'TableName' => 'book',
        'KeySchema' => array(
                'HashKeyElement' => array(
                        'AttributeName' => 'id',
                        'AttributeType' => AmazonDynamoDB::TYPE_NUMBER
                )
        ),
        'ProvisionedThroughput' => array(
                'ReadCapacityUnits' => 50,
                'WriteCapacityUnits' => 10
        )
));

//comment
$ddb->create_table(array(
        'TableName' => 'comment',
        'KeySchema' => array(
                'HashKeyElement' => array(
                        'AttributeName' => 'book_id',
                        'AttributeType' => AmazonDynamoDB::TYPE_NUMBER
                ),
                'RangeKeyElement' => array(
                        'AttributeName' => 'posted_at',
                        'AttributeType' => AmazonDynamoDB::TYPE_NUMBER
                )
        ),
        'ProvisionedThroughput' => array(
                'ReadCapacityUnits' => 50,
                'WriteCapacityUnits' => 10
        )
));

この際、テーブルの作成には時間が多少かかるので、テーブルを作成した後に続けて
データ追加処理等を行う場合は、以下のように待機します。

foreach(array('book', 'comment') as $table_name){
  $count = 0;
  echo $table_name . " : status ";
  do {
    sleep(1);
    $count++;
    $res = $ddb->describe_table(array(
      'TableName' => $table_name
    ));
    $status = (string)$res->body->Table->TableStatus;
    echo ($status === 'ACTIVE' ? $status . "n" : '.');
  }
  while ((string) $res->body->Table->TableStatus !== 'ACTIVE');
}

出力は以下のようになります。

book : status ...........................ACTIVE
comment : status ACTIVE

○テーブルの削除

テーブルの削除は以下のように行います。

foreach(array('book', 'comment') as $table_name){
        $ddb->delete_table(
                array('TableName' => $table_name)
        );
}

DynamoDBは、RDBとは違うので、データの構成等に工夫が必要ですが、RDBとの使い分けで非常に高い効果を
発揮すると思います。
尚、東京リージョンへの展開が待ち遠しいですが、US-Eastに立てたインスタンスからはRTTがないので、ハイパフォーマンスを体験できます。

こちらの記事はなかの人(memorycraft)監修のもと掲載しています。
元記事は、こちら

三浦 悟

三浦 悟

高円寺在住のなんじゃ系男子 またの名をmemorycraftといいます。 炭水化物大好き 日々の「なんじゃ?」を記事にしてます。

cloudpack

cloudpackは、Amazon EC2やAmazon S3をはじめとするAWSの各種プロダクトを利用する際の、導入・設計から運用保守を含んだフルマネージドのサービスを提供し、バックアップや24時間365日の監視/障害対応、技術的な問い合わせに対するサポートなどを行っております。
AWS上のインフラ構築およびAWSを活用したシステム開発など、案件のご相談はcloudpack.jpよりご連絡ください。