入门阅读约 5 分钟

DynamoDB PartiQL 与 SQL:什么会失效

DynamoDB PartiQL 最大的困惑来源——无论对人还是对 AI 助手——就是把它当成关系型 SQL。它不是。PartiQL 是 DynamoDB 现有操作之上的一个兼容 SQL 的表层,而不是一个能连接、分组或聚合的查询引擎。那些熟悉的关键字,掩盖了底层一台截然不同的机器。

DynamoDB PartiQL 与 SQL 有何不同?

PartiQL 借用了 SQL 的语法,却没有借用它的引擎。在 DynamoDB 上,每条语句都映射到单个原生操作——GetItemQueryScanPutItemUpdateItemDeleteItem——所以没有 JOINGROUP BY、子查询或聚合。它读起来像 SQL,但只能做那些键值操作本就能做的事。

每条 PartiQL 语句都会向下编译成 DynamoDB 的某一个原生操作:

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

没有哪个规划器能从两张表读取、构建哈希连接,或把多行折叠成一个 COUNT。如果某个操作无法映射到单个 Get/Query/Scan/Put/Update/Delete,PartiQL 就是表达不了它。这就是全部真相——下面的一切都是这一个事实的推论。

同样的映射,以流程呈现——WHERE 子句决定一个 SELECT 是一次廉价的 Query,还是一次全表 Scan

WHERE pins full PKno PK in WHEREPartiQL statementSELECT?Query (one partition)Scan (whole table)INSERT PutItemUPDATE UpdateItemDELETE DeleteItem

每条语句都解析为恰好一个原生操作——正是这种一对一映射,让 PartiQL 无法连接、分组或聚合。

有何不同——逐项对比

只要 Workbench 那一列标着、而 PartiQL 标着,那就是 DynoTable 的 SQL 弥补的一处空缺。Workbench 通过 DynamoDB 真实的查询运行时把你的表物化出来,然后在其之上运行真正的 SQL——在 DynamoDB 访问模式规则之内的 SQL。

功能标准 SQLDynamoDB PartiQLDynoTable Workbench
JOIN … ON …是 —— INNER / LEFT(连到一个 PK 或 GSI 分区键)
RIGHT / FULL / CROSS / 逗号连接
自连接(Self-join)否(暂不支持)
子查询 / 派生表
CTE(WITH …
UNION / INTERSECT / EXCEPT
GROUP BY / HAVING
聚合(COUNT/SUM/AVG/MIN/MAX
DISTINCT
CASE / CAST
窗口函数
ORDER BY是,任意列部分——仅排序键(需要分区键 WHERE是,任意列
LIMIT无内联写法(用请求的 limit 参数)
LIKE否(用 contains / begins_with
IS NULL / IS NOT NULL是(缺失的属性是 MISSING,而非 NULL——用 IS MISSING
没有 PK 的 SELECT *触发扫描部分——悄无声息的全表 Scan是(带开销可见性)

什么会失效,以及为什么

这些是 DynoTable 的 PartiQL 校验器在查询触网之前就会标出的失败——每一个都追溯到一条真实的 DynamoDB 约束。

  • 没有 SELECT * 是一次隐藏的 Scan PartiQL 不会报错;它只是读取每一个项、之后再过滤,这正是那个藏在友好语法背后的经典 Query 与 Scan 开销之坑。
  • UPDATE / DELETE 需要完整的主键。 它们映射到单项的 UpdateItem/DeleteItem,所以 WHERE 必须锁定分区键(在 表上还要锁定排序键)。你无法在一条语句里"更新所有 status = 'open' 的行"。
  • 双引号是标识符,不是字符串。 DynamoDB PartiQL 在这里遵循 SQL 标准:"name" 是列名/表名,'name' 是字符串值。用双引号引一个值是最常见的新手错误——校验器的提示原话就是 "Double quotes delimit identifiers in DynamoDB PartiQL, not strings. Use single quotes for string values."
  • IN 用方括号,不用圆括号: WHERE pk IN ['a','b'],上限为 50 个 PK 值 / 100 个非键值。
  • 没有 JOIN、没有聚合。 没有引擎去合并表或折叠行。这就是 单表设计 的取舍:你要提前围绕访问模式建模,因为查询层事后无法重塑数据。

为什么 AI 助手会搞错

LLM 是在浩如烟海的关系型 SQL 上训练出来的,所以它们会理直气壮地对 DynamoDB 抛出 JOINGROUP BYLIKE、内联的 LIMIT,以及双引号字符串字面量——而这些 DynamoDB 全都拒绝。DynoTable 自己的模型查询自动修复功能存在的原因,恰恰就是廉价模型会稳定地产出这些模式:它会剥掉双重转义的引号,把 LIKE '%x%' 改写成 contains,把 IS NULL 改写成 attribute_not_exists,并把内联的 LIMIT 提升为请求参数。如果你的 AI 生成的"PartiQL"读起来像 Postgres,那就是破绽。

每张卡片展示关系型开发者惯用的 SQL、DynamoDB PartiQL 对它的实际处理方式,以及背后的原因。标记为“可在 DynoTable 中运行”的卡片,会展示工作台能够运行的等效 SQL。
Joining two tables
PartiQL 不支持
SELECT o.id, c.name
FROM orders o
JOIN customers c ON o.customerId = c.PK
GROUP BY and aggregates
PartiQL 不支持
SELECT country, COUNT(*) AS orders, SUM(total) AS revenue
FROM orders
GROUP BY country
Subqueries
PartiQL 不支持
SELECT * FROM orders
WHERE customerId IN (SELECT PK FROM customers WHERE country = 'ES')
UNION across tables
PartiQL 不支持
SELECT PK FROM orders
UNION
SELECT PK FROM archived_orders
SELECT * (the hidden Scan)
可用,但有限制
SELECT * FROM orders
Updating many rows by a filter
PartiQL 不支持
UPDATE orders SET status = 'shipped'
WHERE status = 'open'
Quoting string values
可用,但有限制
SELECT * FROM users WHERE "name" = "Alice"

DynoTable 的 SQL Workbench:PartiQL 跑不了的查询

当你确实需要一个 JOIN 或一个 GROUP BY 时,答案是 DynoTable 的 SQL Workbench。它会对每个 JOIN 的连接侧(to-side)校验其是否为分区键,通过 DynamoDB 真实的 Query/Scan 运行时物化被连接的行,然后在其之上运行单条 SELECT(聚合、GROUP BYDISTINCTCASECAST)——在 DynamoDB 访问模式规则之内的 SQL。

-- Runs in the DynoTable Workbench (NOT in 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

诚实的约束(Workbench 强制执行 DynamoDB 的访问模型,它不会假装自己是 Postgres):

  • 仅支持 INNER JOINLEFT JOIN——ON 的连接侧属性必须是分区键或 GSI 分区键。不支持 RIGHT / FULL / CROSS / 逗号连接。
  • 暂不支持自连接、子查询、派生表、窗口函数。
  • 连接与投影作用于标量属性。

如果你只是需要为原始 API 拼装条件和键表达式,DynamoDB Expression Builder 会生成正确的 FilterExpression / KeyConditionExpression,完全不必碰 PartiQL 表层。想把 PartiQL 用对,参见完整演示的 PartiQL 示例;想估算任意查询的开销,用 项大小计算器。注意,PartiQL 从不改变传输格式——值仍然以 DynamoDB-JSON 的形式传输。在挑客户端?看看 Workbench 相对一个 普通 DynamoDB GUIDynobase 的定位。

常见问题

PartiQL 和 SQL 是一回事吗? 不是。PartiQL 是一种兼容 SQL 的查询语言,但在 DynamoDB 上它只暴露那些能映射到单个 Get/Query/Scan/Put/Update/Delete 的操作。它没有连接、聚合、子查询或 GROUP BY

DynamoDB PartiQL 能做 JOIN 吗? 不能。DynamoDB PartiQL 无法连接表。DynoTable 的 SQL Workbench 可以通过 DynamoDB 真实的查询运行时物化数据,来运行 INNER/LEFT JOIN(连到一个分区键或 GSI 分区键)。

DynamoDB PartiQL 支持 GROUP BY 或 COUNT 吗? 不支持——DynamoDB PartiQL 里没有聚合,也没有 GROUP BY。对于 COUNT/SUM/AVG/GROUP BY/HAVING 查询,请用 DynoTable 的 SQL Workbench。

为什么我的 SELECT * 开销这么大? 因为 WHERE 里没有分区键,PartiQL 会运行一次全表 Scan,并在过滤生效之前对读取的每个项计费。加一个分区键谓词,把它变成一次 Query

在 PartiQL 里该用单引号还是双引号? 字符串值用单引号('CUSTOMER#42'),表名、属性名之类的标识符用双引号("AppData")。用双引号引一个值是最常见的 PartiQL 错误。

准备好对 DynamoDB 运行真正的 SQL 了吗?下载 DynoTable 并打开一个 Workbench 标签页。

更新于