入门阅读约 2 分钟

如何查看、浏览和编辑 DynamoDB 数据

你对一张 DynamoDB 表的每次"查看"或"更改"都映射到一小组 API 操作之一——GetItemQueryScanPutItemUpdateItemDeleteItem。 底层没有关系型表查看器:"浏览一张表"字面上就是一次 Scan,而"编辑一行"就是针对主键的一次 UpdateItem。知道每次点击 映射到哪个操作,是廉价读取与你无意中运行的整表 扫描之间的区别。

DynoTable 正是这些操作之上的一个 GUI——它在操作触及线缆之前, 向你展示你将要运行哪一个,以及成本。

如何浏览 DynamoDB 表

打开一张表"看看里面有什么"是一次 Scan——它读取表 或索引中的每个项(AWS: "Amazon DynamoDB 中的 Scan 操作读取表或辅助索引中的每个项。")。 对小表没问题;对大表它就是 query vs scan 中讲的经典成本陷阱。

单次 Scan 最多返回 1 MB 数据,然后给你一个 LastEvaluatedKey 来 获取下一页——所以"浏览整张表"其实是一个分页循环 (AWS: "单次 Scan 请求最多可检索 1 MB 数据",且 "Scan 响应中的 LastEvaluatedKey 应作为下一次 Scan 请求的 ExclusiveStartKey")。参见 分页了解游标如何工作,以及为什么这里不存在 偏移式的页码。

如何过滤 / 扫描 DynamoDB 数据

陷阱:过滤表达式不会为你省下一次扫描。DynamoDB 在读取 完成之后才应用过滤器,所以你为扫描的每个项付费——而不仅是你 保留的行。

过滤表达式在 Scan 完成之后、结果返回之前 应用。因此,无论是否存在过滤表达式,Scan 都消耗相同 数量的读容量。 — AWS Scan 文档

响应让这一点可见:ScannedCount 是"在应用任何 ScanFilter 之前所评估的项数",而 Count 是经过过滤器幸存下来的 (AWS)。 高 ScannedCount 配极小的 Count 正是低效扫描的特征。

如何查询 DynamoDB 表

Query 是廉价、精准的读取——但它需要一个分区键。根据 AWS: "你必须提供分区键属性的名称和该属性的单个值。Query 返回具有该分区键值的所有项。可选地, 你可以提供一个排序键属性并使用比较运算符来细化搜索结果。"

所以一次 Query 只读取一个分区键下的项,可选地由 排序键条件缩小范围——从不读取整张表。没有分区键,就没有 Query:你 又回到了 Scan。这个选择是 DynamoDB 中最重要的单个 成本决策;完整剖析见 query vs scan

要组装 KeyConditionExpression / FilterExpression 而不手写 占位符语法,用 DynamoDB 表达式构建器——它发出 API 期望的确切名称/值映射。

如何编辑 DynamoDB 中的一个项

编辑一个项是针对其完整主键的一次 UpdateItem。你不会 重写整个项——你提供一个更新表达式,只命名你正在 更改的属性:

UpdateItem
  Key:              { "PK": "USER#42", "SK": "PROFILE" }
  UpdateExpression: SET email = :e, updatedAt = :t

两个绊倒人的事实,都来自 AWS 项文档

  • 你必须指定整个主键,而非它的一部分。 在 复合键表上那是分区键排序键。你无法通过一个 任意属性来"编辑一行"——那需要先扫描找到键。
  • UpdateItem 是一次 upsert。 "如果不存在具有指定键的项, UpdateItem 会创建一个新项。否则,它会修改一个现有项的 属性。" 键中的一个拼写错误会静默创建一个新项而非 报错。

如何删除一个项

一次 DeleteItem,同样以完整主键为键: "DeleteItem 删除具有指定键的项" (AWS)。 与编辑同一条规则——你需要整个键,所以删除"所有 status = 'open' 的行"不是一次调用;你要扫描/查询找到这些键,然后逐个删除。 BatchWriteItem 打包最多 25 个 put/delete 请求 (AWS: "BatchWriteItem 操作最多可包含 25 个独立的 PutItemDeleteItem 请求"),但每个仍然针对一个键——没有 DELETE … WHERE

如何查看嵌套 / JSON 数据

DynamoDB 项以一种带类型标签的线缆格式(DynamoDB-JSON)存储,其中每个 值都携带一个一或两字母的类型描述符(SNMLSS……—— 完整的描述符列表在 AWS 数据类型文档中)。 普通 JSON 没有集合类型,所以一个数组往返时会变成列表(L),从不 是字符串集合(SS)——这是真正的转换限制,而非显示 bug。完整的类型映射在 DynamoDB 数据类型中;要把一个 DynamoDB-JSON 数据块转换成普通 JSON 再转回去,用 DynamoDB JSON 转换器

超越浏览与编辑:DynamoDB 做不到的查询

Scan/Query/UpdateItem 涵盖查看和编辑,但它们无法分析—— DynamoDB 没有 JOINGROUP BYCOUNT/SUM 这样的聚合函数,且 PartiQL 也没有添加它们:它的 SELECT 语法 只是 SELECT … FROM table [WHERE …] [ORDER BY …],没有连接或分组子句 (AWS PartiQL SELECT 参考), 所以每条语句映射到单个 Get/Query/Scan/Put/Update/Delete。DynoTable 的 SQL Workbench 通过 DynamoDB 真正的查询运行时把你的表物化并 在其上运行 SQL 来填补那个缺口——在 DynamoDB 的访问模式规则内的 SQL—— 但对于日常的浏览与编辑,上面的操作就是整个工具箱。

常见问题

如何在不用 AWS 控制台的情况下查看 DynamoDB 数据? 用一个发出同样 Scan/Query 调用的桌面 GUI。AWS 控制台 通过分页扫描浏览表;像 DynoTable 这样的专用客户端做同样的事,但 会显示消耗的容量和你正在运行的操作。

如何编辑一个 DynamoDB 项? 针对项的完整主键发出一次 UpdateItem,并用一个只命名你正在 更改的属性的 SET 更新表达式。在 GUI 中,内联编辑那个 单元格——它会为你编译成那次 UpdateItem

为什么过滤仍然花费一次整表扫描? 因为 DynamoDB 在扫描读取这些项之后才应用过滤器。被过滤掉的 项仍被读取并计量。要降低成本,按一个分区键(或一个 GSI)查询,而不是扫描。

我能一次更新很多项吗? 不能在一次调用中。UpdateItem/DeleteItem 各自针对单个主键;没有 UPDATE … WHERE。你要扫描/查询来收集这些键,然后逐个写入(每个 BatchWriteItem 最多 25 个)。

我能用同样的方式浏览一张 DynamoDB Local 表吗? 能——把同一个 GUI 指向本地端点。参见 DynamoDB Local

想浏览、过滤和内联编辑 DynamoDB 表——并运行 PartiQL 做不到的 SQL?下载 DynoTable

更新于