如何获取DynamoDB表中的项目总数?

时间:2012-09-19 17:25:02

标签: php amazon-dynamodb

我想知道我的dynamodb表中有多少项。从API指南中,一种方法是使用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 Web控制台中不可用,我已经检查过了。 (起初看起来它显示在分页按钮旁边,但事实证明,当你转到下一页的项目时,数字会增长。)

8 个答案:

答案 0 :(得分:23)

我可以考虑三个选项来获取DynamoDB表中的项目总数。

  1. 第一个选项是使用扫描,但扫描功能效率低,通常是一种不好的做法,特别是对于读取量很大或生产表较多的表。

  2. 第二种选择是Atharva提到的:

      

    我想到的一个更好的解决方案是保持总数   单独表格中此类表格的项目计数,每个表格   item将具有表名作为其哈希键和项目总数   在该表中,因为它是非键属性。然后你可以保留这个表   可能通过制作原子来更新名称“TotalNumberOfItemsPerTable”   更新操作以增加/减少a的总项数   特别的表。

    唯一的问题是增量操作不是幂等的。因此,如果写入失败或您不止一次写入,这将反映在计数中。如果您需要精确定位,请改用条件更新。

  3. 最简单的解决方案是DescribeTable,它返回ItemCount。唯一的问题是计数不是最新的。计数每6小时更新一次。

  4. http://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_DescribeTable.html

答案 1 :(得分:13)

Count选项绝对是您想要的,但您还必须考虑扫描结果中可能有一个或多个“页面”结果。扫描操作一次只扫描表中的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}";

答案 2 :(得分:6)

啊哈,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";

答案 3 :(得分:4)

如果您有兴趣在应用程序逻辑中使用表中的项目总数,这意味着您将经常查询总计数。现在,实现此目的的一种方法是使用扫描操作。但请记住,扫描操作会扫描整个表,因此会消耗大量吞吐量,因此所有查询操作都将在该持续时间内收到Throttled Exception。甚至考虑到扫描将结果数量限制为1MB的大小这一事实,如果表格非常大,您将不得不进行重复扫描操作以获得实际的项目数。这将需要编写自定义查询逻辑并处理查询操作中不可避免的限制。

我想到的一个更好的解决方案是在一个单独的表中维护这些表的项目总数,其中每个项目都有表名作为它的散列键和该表中的项目总数,因为它是非-key属性。然后,您可以通过使原子更新操作增加/减少特定表的总项数来更新此表可能名为“TotalNumberOfItemsPerTable”。

没有限制问题或1MB限制。

此外,您可以将此概念扩展到更进一步的粒度,例如,以维护与某些散列键匹配的项目总数或您可以以字符串形式编码的任意条件,以在您的表中创建名为“TotalNumberOfItemsInSomeCollection”的条目“或”TotalNumberOfItemsMatchingSomeCriteria“。然后,这些表可以包含每个表,每个集合的项目数或与某些条件匹配的项目的条目。

答案 4 :(得分:2)

适用于DynamoDB的AWS控制台中提供了近似项目计数值(假设每六小时更新一次)。只需选择表格并在详细信息选项卡下查看,最后一项是项目计数。如果这对您有用,那么您可以避免消耗您的表吞吐量来进行计数。

答案 5 :(得分:1)

现在可以在AWS表概述屏幕的“表详细信息”部分的“项目计数”字段下找到。它似乎只是DescribeTable的转储,并指出它大约每六个小时更新一次。

答案 6 :(得分:0)

这里是我如何获得我的十亿记录DynamoDB表的确切项目数:

蜂房&GT;

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处理程序会发出&#34; PARALLEL SCANS&#34;使用多个Mapreduce映射器(AKA Workers)处理不同的分区以获取计数。这将比普通扫描更有效,更快 *您必须愿意在一段时间内提高读取容量。 *在体积适中(20节点)的群集上,使用10000 RCU,花费15分钟来计算数十亿条记录 *在此期间对此DDB表的新写入将使计数不一致。

答案 7 :(得分:0)

请不要使用dynamoDb的扫描方法,因为它会读取表格的所有数据,但是在这种情况下,您只需要计数即可,因此请使用此方法。

$scan_response = $dynamodb->describeTable(array(
'TableName' => 'ProductCatalog' ));

并将其打印为结果$scan_response['Table']['ItemCount']