【问题标题】:How can I get the total number of items in a DynamoDB table?如何获取 DynamoDB 表中的项目总数?
【发布时间】:2022-01-10 13:14:54
【问题描述】:

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

【问题讨论】:

标签: php amazon-dynamodb


【解决方案1】:

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

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

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

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

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

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

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

【讨论】:

  • 可以使用TransactWriteItems API 创建一个原子操作,将其放入主表并更新 TotalNumberOfItemsPerTable 表吗?
【解决方案2】:

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

【讨论】:

    【解决方案3】:

    啊哈,scan API 中有一个Count 选项,请参阅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";
    

    【讨论】:

    • 正如 Jeremy Lindblom 在他的回答中提到的,并证明了这一点:docs.aws.amazon.com/amazondynamodb/latest/developerguide/… 确保您注意 1MB 限制,即如果您的表大小大于返回的计数可能是部分计数1MB。
    • 每当我运行上述代码时,我都会得到以下信息:Fatal error: Class 'DynamoMetadata' not found in C:\Users\Lenovo\xampp\public_html\upload_file.php on line 73。怎么解决?
    【解决方案4】:

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

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

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

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

    【讨论】:

      【解决方案5】:

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

      【讨论】:

        【解决方案6】:

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

        【讨论】:

          【解决方案7】:

          以下是我在十亿条记录的 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 表的新写入会导致计数不一致。

          【讨论】:

            【解决方案8】:

            这就是我的做法:

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

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

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

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

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

            注意:如果您对扫描会话进行适当计时以加载读取容量,同时为自动缩放留出时间为您增加容量(扫描完成后容量会下降),则同样的事情也适用于自动缩放

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

            【讨论】:

              【解决方案9】:

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

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

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

              【讨论】:

              • 这不是他最好的方法,因为计数可能不是最新的,它每 6 小时更新一次。
              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2012-02-26
              • 1970-01-01
              • 1970-01-01
              • 2021-12-12
              相关资源
              最近更新 更多