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

32

我想知道我的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控制台中不可用,我已经检查过了。(起初,它似乎与分页按钮一起显示,但随着您转到下一页的项目,该数字会增加)。


使用DescribeTable,详见此处:http://stackoverflow.com/a/37036989/3305145 - Tyler
9个回答

32
我能想到三种方法来获取 DynamoDB 表的总项目数:
  1. 第一种选项是使用扫描 (scan) 方法,但是这个方法效率低下,在通常情况下不推荐使用,特别是对于有大量读取或生产表的情况。
  2. 第二种选项是 Atharva 提到的:

    我想到的更好的解决方案是在一个单独的表中维护此类表的总项目数, 每个项目将以其表名为哈希密钥,以该表中的项目总数为非键属性。然后, 您可以通过进行原子更新操作来增加/减少特定表的总项目计数,并保持此表(可能命名为 "TotalNumberOfItemsPerTable")的最新状态。

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

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

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


TransactWriteItems API能否用于创建原子操作,将数据放入主表并更新TotalNumberOfItemsPerTable表? - papiro

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}";

7

2
正如Jeremy Lindblom在他的回答中所提到的,并且通过这个链接所证明的:http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/QueryAndScan.html,请确保您注意1MB限制,即如果您的表大小大于1MB,则返回的计数可能是部分计数。 - Atharva
每当我运行上述代码时,都会出现以下错误:致命错误:在C:\ Users \ Lenovo \ xampp \ public_html \ upload_file.php的第73行找不到“ DynamoMetadata”类。如何解决? - Ido Naveh

6
如果您希望在应用程序逻辑中使用表中的总项目数,这意味着您将经常查询总计数。现在,实现此目标的一种方法是使用扫描操作。但请记住,扫描操作会完全扫描整个表,因此会消耗大量吞吐量,因此在此期间所有查询操作都将收到限流异常。即使考虑到扫描将通过1MB的大小限制结果计数,如果表非常大,则必须进行重复的扫描操作才能获得实际项目数。这将需要编写自定义查询逻辑并处理查询操作中不可避免的限流。
我想到的更好的解决方案是,在单独的表中维护此类表的项目总数,其中每个项目都将具有表名作为其哈希键和该表中项目的总数作为其非键属性。然后,通过进行原子更新操作来增加/减少特定表的总项目计数来保持此表(可能命名为“TotalNumberOfItemsPerTable”)更新。
没有限流或1MB限制问题。
此外,您甚至可以将此概念扩展到更细粒度,例如维护与某个哈希键或任何任意标准匹配的项目的总数,您可以以字符串形式对其进行编码,以便在名为“TotalNumberOfItemsInSomeCollection”或“TotalNumberOfItemsMatchingSomeCriteria”的表中进行输入。然后,这些表可以包含每个表、每个集合或与某些标准匹配的项目数的条目。

3

在DynamoDB的AWS控制台中,可以获取大约每六个小时更新一次的项目数值。只需选择表格,然后查看详细信息标签页,最后一个条目是项目数。如果这对您有用,则可以避免使用表格吞吐量进行计数。


1

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


1
这是我的做法:
  • 进入DynamoDB控制台
  • 选择一个表格
  • 概览(选择表格后默认显示的页面)
  • 向下滚动到“摘要”部分
  • 查看每6小时更新一次的3个值,即计数、大小和平均项大小。
  • 点击“获取实时项计数”按钮
  • 点击“开始扫描”

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

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

安全地执行此操作以最小化限制其他流量的风险的方法:

  • 增加读取容量单位(可以是高设置而不带自动缩放或将最小值设置为高数字)
  • 等待更高的容量出现(红点)在云监控中的读取使用度量或在DynamoDB控制台中(在与“获取实时计数”操作标签/窗口不同的标签/窗口中)
  • 点击扫描按钮并等待几秒钟,然后暂停
  • 检查2分钟后图表上的增加使用情况(在其他标签/窗口中),以查看它如何影响读取使用情况
  • 重复扫描/暂停过程,使用您可以接受的风险定时间隔,直到扫描完成并结果时间戳为止
  • 您将看到计数总数以及完成计数操作的日期/时间戳
  • 记下信息,在关闭窗口时完全丢失!
  • 将预留读取容量重置回原来的位置,以避免产生额外的费用

注意:如果您按时计划扫描会话以加载读取容量并给自动缩放增加时间,则自动缩放也可能有效。

另一种方法可能是切换到按需预留,执行上述扫描,然后再切换回预留容量,但我没有测试过,因此不确定按需能否保证处理所需的容量要求而不会被限制。


0
这是我如何在拥有十亿条记录的 DynamoDB 表上获取准确的项目计数的方法:
hive>
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处理程序会发出“PARALLEL SCANS”,多个Mapreduce映射器(也称为工作程序)在不同的分区上工作以获取计数。这比普通扫描更有效率和更快。
*您必须愿意在一定时间内将读取容量提高到非常高的水平。 *在一个体量适中的(20个节点)集群上,使用10000 RCU,大约需要15分钟才能对十亿条记录进行计数。
*在此期间对此DDB表进行的新写入将使计数不一致。


0
请不要使用 DynamoDB 的扫描方法,因为它会读取表中的所有数据,但在这种情况下,您只需要计数,所以请使用以下方法。
$scan_response = $dynamodb->describeTable(array(
'TableName' => 'ProductCatalog' ));

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


这不是最好的方法,因为计数可能不是最新的,它每6小时更新一次。 - PatrykMilewski

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接