Dynamodbテーブルにいくつのアイテムがあるのか知りたい。 APIガイドから、それを行う1つの方法は、次のように scan を使用することです。
<?php
$dynamodb = new AmazonDynamoDB();
$scan_response = $dynamodb->scan(array(
'TableName' => 'ProductCatalog'
));
echo "Total number of items: ".count($scan_response->body->Items)."\n";
ただし、これはすべてのアイテムをフェッチしてメモリ内の配列に格納する必要があるため、ほとんどの場合、私が推測することはできません。アイテムの総数をより効率的に取得する方法はありますか?
このデータはAWS Dynamoウェブコンソールでは利用できません。すでに確認しました。 (最初は、ページ付けボタンの横に表示されているように見えますが、次のページのアイテムに移動すると、図が大きくなることがわかります)。
DynamoDBテーブル内のアイテムの総数を取得するには、3つのオプションが考えられます。
最初のオプションはスキャンを使用することですが、スキャン機能は非効率的であり、一般に、特に読み取りが多いテーブルや本番テーブルの場合は悪い習慣です。
2番目のオプションは、Atharvaによって言及されたものです。
私の頭に浮かぶより良い解決策は、そのようなテーブルのアイテム数の合計数を個別のテーブルに維持することです。各アイテムは、ハッシュキーとしてテーブル名を持ち、非キー属性としてそのテーブル内のアイテムの総数を持ちます。 。次に、特定のテーブルの合計アイテムカウントをインクリメント/デクリメントするアトミック更新操作を行うことにより、「TotalNumberOfItemsPerTable」という名前のこのテーブルを更新された状態に保つことができます。
唯一の問題は、インクリメント操作がべき等ではないことです。したがって、書き込みが失敗した場合、または複数回書き込んだ場合、これはカウントに反映されます。ピンポイントの精度が必要な場合は、代わりに条件付き更新を使用してください。
最も簡単な解決策は、ItemCountを返すDescribeTableです。唯一の問題は、カウントが最新でないことです。カウントは6時間ごとに更新されます。
http://docs.aws.Amazon.com/amazondynamodb/latest/APIReference/API_DescribeTable.html
Count
オプションは間違いなく必要なものですが、スキャン結果に結果の「ページ」が1つ以上存在する可能性があることも考慮する必要があります。 Scanオペレーションは、一度にテーブル内の1MBのデータのみをスキャンするため、結果のCount
の値は、テーブルの最初の1MBのカウントのみを反映します。結果にLastEvaluatedKey
の値を使用して後続のリクエストを行う必要があります(ある場合)。これはそのようなことをするためのサンプルコードです:
<?php
$dynamo_db = new AmazonDynamoDB();
$total = 0;
$start_key = null;
$params = array(
'TableName' => 'my-table',
'Count' => true
);
do {
if ($start_key) {
$params['ExclusiveStartKey'] = $start_key->getArrayCopy();
}
$response = $dynamo_db->scan($params);
if ($response->isOK()) {
$total += (string) $response->body->Count;
if ($response->body->LastEvaluatedKey) {
$start_key = $response->body->LastEvaluatedKey->to_array();
} else {
$start_key = null;
}
}
} while ($start_key);
echo "Count: {$total}";
ああ、Count
APIにはscan
オプションがあります。参照 http://docs.amazonwebservices.com/AWSSDKforPHP/latest/#m=AmazonDynamoDB/scan
<?php
$dynamodb = new DynamoMetadata();
$scan_response = $dynamodb->scan(array(
'TableName' => 'ProductCatalog'
'Count' => true,
));
echo "Count: ".$scan_response->body->Count."\n";
アプリケーションのロジックでテーブル内のアイテムの総数を使用することに関心がある場合は、合計カウントをかなり頻繁にクエリすることになります。これを実現する1つの方法は、スキャン操作を使用することです。ただし、スキャン操作は文字通りテーブル全体をスキャンするため、大量のスループットを消費するため、すべてのクエリ操作がその期間にスロットル例外を受け取ることに注意してください。また、スキャンによって結果の数が1MBのサイズに制限されるという事実を考慮しても、テーブルが非常に大きい場合は、スキャン操作を繰り返して実際のアイテム数を取得する必要があります。これには、カスタムクエリロジックを記述し、クエリ操作で不可避のスロットルを処理する必要があります。
私の頭に浮かぶより良い解決策は、そのようなテーブルのアイテム数の合計数を個別のテーブルに維持することです。各アイテムは、ハッシュキーとしてテーブル名を持ち、非キー属性としてそのテーブル内のアイテムの総数を持ちます。 。次に、特定のテーブルの合計アイテムカウントをインクリメント/デクリメントするアトミック更新操作を行うことにより、「TotalNumberOfItemsPerTable」という名前のこのテーブルを更新された状態に保つことができます。
スロットリングや1MBの制限の問題はありません。
さらに、この概念をさらに細かく拡張して、たとえば、ハッシュキーや、文字列形式でエンコードして「TotalNumberOfItemsInSomeCollection」や「 TotalNumberOfItemsMatchingSomeCriteria」をご覧ください。これらのテーブルには、テーブルごと、コレクションごと、またはいくつかの基準に一致するアイテムごとの項目数のエントリを含めることができます。
おおよそのアイテム数の値(6時間ごとに更新されると思われます)は、DynamoDBのAWSコンソールで利用できます。テーブルを選択して[詳細]タブを確認するだけです。最後のエントリは[アイテム数]です。これでうまくいく場合は、カウントのためにテーブルのスループットを消費することを回避できます。
これは、AWSテーブルの概要画面の「テーブルの詳細」セクションの「アイテム数」フィールドで利用できるようになりました。それは、DescribeTableの単なるダンプのようであり、約6時間ごとに更新されることに注意してください。
10億レコードのDynamoDBテーブルで正確なアイテム数を取得する方法は次のとおりです。
ハイブ>
set dynamodb.throughput.write.percent = 1;
set dynamodb.throughput.read.percent = 1;
set Hive.execution.engine = mr;
set mapreduce.reduce.speculative=false;
set mapreduce.map.speculative=false;
CREATE EXTERNAL TABLE dynamodb_table (`ID` STRING,`DateTime` STRING,`ReportedbyName` STRING,`ReportedbySurName` STRING,`Company` STRING,`Position` STRING,`Country` STRING,`MailDomain` STRING) STORED BY 'org.Apache.hadoop.Hive.dynamodb.DynamoDBStorageHandler' TBLPROPERTIES ("dynamodb.table.name" = "BillionData", "dynamodb.column.mapping" = "ID:ID,DateTime:DateTime,ReportedbyName:ReportedbyName,ReportedbySurName:ReportedbySurName,Company:Company,Position:Position,Country:Country,MailDomain:MailDomain");
SELECT count(*) FROM dynamodb_table;
* EMRクラスターが必要です。これには、HiveおよびDynamoDBレコードハンドラーがインストールされています。 *このコマンドを使用すると、Hive上のDynamoDBハンドラーは、複数のMapreduceマッパー(AKAワーカー)が異なるパーティションで作業してカウントを取得することにより、「PARALLEL SCANS」を発行します。これは、通常のスキャンよりもはるかに効率的で高速です。
*一定期間、読み取り容量を非常に高くすることをいとわない必要があります。 *適切なサイズ(20ノード)のクラスターで10000 RCUを使用すると、数十億のレコードをカウントするのに15分かかりました。
*この期間中にこのDDBテーブルに新しい書き込みを行うと、カウントが不整合になります。
Tabelのすべてのデータを読み取るため、dynamoDbのスキャンメソッドを使用しないでください。ただし、この場合はカウントする必要があるだけなので、これを使用してください。
$scan_response = $dynamodb->describeTable(array(
'TableName' => 'ProductCatalog' ));
これを結果$scan_response['Table']['ItemCount']
に出力します