入门阅读约 3 分钟

SQL for DynamoDB:什么可行、什么不可行,以及 Workbench

DynamoDB 是一个 NoSQL 键值存储,但它回答 SQL 式问题的能力 比人们预期的更强——也远不如人们希望的那么多。这是一份诚实的 地图:开箱即用你实际能得到的 SQL-on-DynamoDB、它在哪里止步,以及 运行原生接口无法表达的 JOIN / GROUP BY / 聚合查询的少数 方式。

你能用 SQL 查询 DynamoDB 吗?简短答案

部分能。DynamoDB 自带 PartiQLAWS 文档 把它描述为"一种 SQL 兼容的查询语言,用于在 Amazon DynamoDB 中 选择、插入、更新和删除数据。" 所以你可以写 SELECT * FROM "Orders" WHERE OrderID = 100,它能工作。

但 PartiQL 是 DynamoDB API 之上的一个 SQL 兼容接口,而非一个 SQL 引擎。它说着这门语法;它增加关系型查询能力。AWS 明确指出"Amazon DynamoDB 支持 PartiQL 查询语言的一个子集" (参考)。 一旦你伸手去拿 JOINGROUP BYCOUNT(*),你就超出了 PartiQL 能做的范围——完整的逐项对比见 PartiQL vs SQL

PartiQL:一个 SQL 兼容接口,而非 SQL 引擎

PartiQL 把 SQL 看起来的语句映射到 SDK 暴露的同一批数据平面 操作上。带分区键等值的 SELECT 编译为 Query; 不带分区键的 SELECT 编译为 Scan。根据 AWS SELECT 参考

如果 WHERE 子句中没有提供分区键的等值或 IN 条件,使用 SELECT 语句可能导致整表扫描。

所以管辖 QueryScan 的同一套访问模式规则仍然适用—— PartiQL 只是把它们藏在熟悉的语法背后。它不增加查询规划器、不增加 连接,也不增加基于集合的聚合。每条语句都坍缩为一个原生 操作:

你写的DynamoDB 运行的
SELECT … WHERE PK = …GetItemQuery
SELECT …(无 PK)Scan(读取整张表
INSERT INTO …PutItem
UPDATE … WHERE PK=… AND SK=…UpdateItem(单个项)
DELETE … WHERE PK=… AND SK=…DeleteItem(单个项)

如果某个操作无法归约为单个 Get/Query/Scan/Put/Update/Delete, PartiQL 就根本无法表达它。下面的一切都是那一个事实的后果。

PartiQL 涵盖什么

DynamoDB 的 PartiQL 支持四种 DML/查询语句:

  • SELECT——读取项(编译为 QueryScan
  • INSERT——添加项(PutItem
  • UPDATE——修改项(UpdateItem
  • DELETE——删除项(DeleteItem

它也支持 事务和批量操作。 一个良构的读取用等值或 IN 锁定 分区键:

SELECT OrderID, Total
FROM "Orders"
WHERE OrderID IN [1, 2, 3] ORDER BY OrderID DESC

ORDER BY 是允许的,但 AWS 参考把排序键限制为"一个 哈希键或一个排序键"——即分区键或排序键,而非任意列。 这就是 PartiQL 的 SELECT 所接受的上限。要拿到可复制粘贴的 语句,参见 PartiQL 示例

PartiQL 做不到什么

这些是开发者最常从"SQL"期待的东西,而 PartiQL 全都不支持

  • 没有 JOIN PartiQL SELECT 语法 是单个 FROM {{table}}[.{{index}}]——一张表或一个索引,从不是两张 在键上关联的表。这是 单表设计的取舍:你提前为 你的访问模式建模,因为查询层无法在事后重塑 数据。
  • 没有 GROUP BY 它不在语法里;没有子句来分组行。
  • 没有聚合函数。 PartiQL 函数参考 在"聚合函数"下只列出一个函数:SIZE,它返回 单个项的属性的字节大小。没有跨行的 COUNTSUMAVGMINMAX。AWS 直白地说明:"任何不在此 列表中的 SQL 函数当前在 DynamoDB 中不受支持。"
  • 没有 LIKE、没有子查询、没有 UNION、没有窗口函数。 模式匹配 用 contains / begins_with;其余的根本没有等价物。

所以"上个月按客户的总收入"——在任何关系型数据库中是一行 GROUP BY——在 PartiQL 中无法表达。你得把数据扫描出来再在 应用代码中聚合。

唯一能对 DynamoDB 数据获得真正 JOIN / GROUP BY / 聚合行为的方式是 一个在其上运行真正 SQL 引擎的工具。有两个: Amazon Athena 的联邦连接器,以及 DynoTable 的 SQL Workbench。

如何通过 Amazon Athena 用真正的 SQL 查询 DynamoDB

AWS 自己对"对 DynamoDB 用真正 SQL"的答案是 Amazon Athena DynamoDB 连接器, 它"让 Amazon Athena 能与 DynamoDB 通信,从而你可以用 SQL 查询 你的表。" 因为 Athena 是一个完整的 SQL 引擎,这确实让你得到 JOIN 和聚合——AWS 的演练标题就是 "使用 Athena 访问、查询和连接 Amazon DynamoDB 表。"

陷阱在于设置和成本:

  • 它是一个你部署到自己账户中的基于 Lambda 的联邦连接器 (通过 Athena 控制台或 Serverless Application Repository),经由 AWS Glue 处理 schema,并把结果溢出到一个 S3 桶 (连接器文档)。
  • 在底层它仍使用 DynamoDB 的 QueryScan API 操作。 AWS 警告"使用扫描的查询可能消耗大量的读容量 单位(RCU)",所以对一张大表的分析型查询会读取——并 计量——大量的项 (连接器成本)。 用项大小计算器来估算 一个扫描密集的查询将花费多少。
  • 通过连接器不支持 INSERT INTO 等写操作。

Athena 是用于计划内分析和 BI 仪表盘的正确工具。对于日常的 "我只是需要连接两张表并大致看看结果"场景,它太重了—— 那正是下一节填补的缺口。

DynoTable SQL Workbench:在 DynamoDB 的访问模式规则内的 SQL

DynoTable 的 SQL Workbench 从桌面客户端对你的实时 DynamoDB 表运行真正的 SQL——JOINGROUP BYCOUNT/SUM/AVG——无需搭建 Lambda、Glue 或 S3。它通过 DynamoDB 真正的 Query/Scan 运行时把行物化, 然后在其上的一个内存引擎中运行你完整的 SQL:

-- 在 DynoTable Workbench 中运行(不在 PartiQL 中):
SELECT c.country, COUNT(*) AS orders, SUM(o.total) AS revenue
FROM orders o
INNER JOIN customers c ON o.customerId = c.PK
GROUP BY c.country
ORDER BY revenue DESC

"在 DynamoDB 的访问模式规则内"这部分很重要。Workbench 不 假装 DynamoDB 是 Postgres——它在底层仍通过 Query/Scan 读取,所以你始终清楚每个查询的成本,且它强制执行 DynamoDB 的 访问模型而非隐藏它:

  • INNER JOINLEFT JOIN——ON 目标属性必须是 分区键或 GSI 分区键。没有 RIGHT / FULL / CROSS / 逗号连接。
  • 尚不支持自连接,没有子查询,没有派生表,没有窗口函数。
  • 连接和投影作用于标量属性。

如果你只需要为原始 API 组合条件和键表达式——而非 一条完整的 SQL 语句——那么 DynamoDB 表达式构建器能生成 正确的 FilterExpression / KeyConditionExpression,完全不需要 PartiQL 接口。

如果你的目标是一个用于探索、调试和分析表的 DynamoDB SQL 客户端,Workbench 填补了那个缺口——而 DynoTable 的其余部分是围绕它的一个 完整 DynamoDB GUI

试用 DynoTable,对你自己的表运行真正的 SQL。

常见问题

你能对 DynamoDB 运行 SQL 吗? 你可以运行 PartiQL,一个 SQL 兼容的子集(按键的 SELECT/INSERT/UPDATE/DELETE)。对于完整 SQL——JOIN、GROUP BY、聚合——你需要 在其上的一个 SQL 引擎:Amazon Athena DynamoDB 连接器,或 DynoTable 的 SQL Workbench。

DynamoDB PartiQL 支持 JOIN 吗? 不支持。PartiQL 的 SELECT 语法只有单个 FROM 表或索引,没有连接 语法。连接需要在 DynamoDB 之上分层的引擎。

PartiQL 支持 GROUP BY 或 COUNT 和 SUM 这样的聚合吗? 不支持。没有 GROUP BY 子句,唯一的"聚合"函数是 SIZE (单个项的属性字节大小)。跨行的 COUNTSUMAVGMINMAX 不受支持。

DynamoDB 是 SQL 还是 NoSQL? NoSQL——一个键值和文档存储。PartiQL 在其上增加一门 SQL 兼容 的查询语言,但 DynamoDB 没有关系引擎、连接或聚合。

PartiQL 适合临时查询吗? 对于基于键的查找,适合。对于分析型临时查询(计数、汇总、 连接),不适合——PartiQL 无法表达它们,而无约束的 SELECT 会静默 变成整表扫描。

有没有处理 JOIN 和 GROUP BY 的 DynamoDB SQL 客户端? 有——DynoTable 的 SQL Workbench 从桌面对实时表运行 JOIN/GROUP BY/聚合,而 Amazon Athena 通过一个你 部署在 AWS 账户中的联邦连接器来实现。

更新于