28

我想知道我的 dynamodb 表中有多少项目。在 API 指南中,一种方法是使用如下扫描:

<?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 控制台中不可用,我已经检查过了。(起初它看起来像是显示在分页按钮旁边,但事实证明,随着您转到下一页项目,这个数字会变大)。

4

9 回答 9

27

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

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

  2. 第二个选项是 Atharva 提到的:

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

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

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

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

于 2014-02-22T18:32:25.880 回答
14

Count选项绝对是您想要的,但您还必须考虑到您的扫描结果中可能有一个或多个“页面”结果。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}";
于 2012-10-05T15:49:35.203 回答
7

啊哈, API中有一个Count选项,请参阅http://docs.amazonwebservices.com/AWSSDKforPHP/latest/#m=AmazonDynamoDB/scanscan

<?php
$dynamodb = new DynamoMetadata();

$scan_response = $dynamodb->scan(array(
    'TableName' => 'ProductCatalog'
    'Count'     => true,
));

echo "Count: ".$scan_response->body->Count."\n";
于 2012-09-19T17:32:28.383 回答
5

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

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

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

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

于 2013-09-18T04:53:28.163 回答
3

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

于 2013-04-01T15:43:52.230 回答
1

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

于 2015-11-27T19:05:24.510 回答
0

以下是我如何在十亿条记录 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 Worker)在不同的分区上工作以获取计数。这将比普通扫描更有效和更快。
*您必须愿意在一段时间内将读取容量提高到非常高的水平。* 在一个相当大的(20 节点)集群上,拥有 10000 个 RCU,需要 15 分钟才能计算十亿条记录。
* 在此期间对该 DDB 表的新写入会导致计数不一致。

于 2016-08-26T16:01:35.673 回答
0

我就是这样做的:

  • 进入 DynamoDB 控制台
  • 选择一个表
  • 概览(选择表的默认登陆)
  • 向下滚动到“摘要”部分
  • 查看“每 6 小时”更新的 3 个值、计数、大小和平均项目大小。
  • 单击“获取实时项目计数”按钮
  • 点击“开始扫描”

我看到计数在增加(与某些答案中提到的 1 MB 分页限制无关),并在达到实时计数时看到“完成”。

这会消耗扫描的读取容量,因此在实际执行此操作之前,最好手动增加预置容量以避免限制其他当前读取流量。您可以随意“暂停”扫描并继续(以允许在部分扫描会话之间建立预置容量。最终,您将达到表中的项目数。

安全地执行此操作以最大程度地减少限制其他流量的风险的方法:

  • 增加读取容量单位(没有自动缩放的高设置或将最小值设置为高数字)
  • 等到在 cloudwatch 或 dynamodb 控制台(在与“获取实时计数”操作选项卡/窗口分开的选项卡或窗口中)的读取使用量指标中显示更高容量(红点)
  • 单击扫描按钮并等待几秒钟,然后暂停
  • 2 分钟后检查图表上的增加使用量(在另一个选项卡/窗口中),看看它如何影响读取使用量
  • 使用您可以接受的风险的时间间隔重复扫描/暂停过程,直到扫描完成并且结果在结果中加上时间戳
  • 您将看到计数总数以及已完成计数操作的日期/时间戳
  • 把信息记下来,关上窗户就完全没了!
  • 将预置读取容量重置回原来的位置以避免产生额外成本

注意:如果您适当地为扫描会话计时以加载读取容量,同时为自动缩放提供时间为您增加容量(扫描完成后容量会下降),则同样的事情可以与自动缩放一起使用

另一种方法可能是切换到按需配置,执行上述扫描,然后切换回配置容量,但我还没有测试过,所以不确定 ON DEMAND 是否能保证在不限制的情况下处理所需的容量要求。

于 2022-01-10T05:14:54.597 回答
-1

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

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

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

于 2019-11-20T14:49:37.403 回答