入門閱讀時間 5 分鐘

DynamoDB PartiQL vs SQL:什麼會失效

DynamoDB 的 PartiQL 最大的困惑來源——無論對人類還是 AI 助理都一樣——就是把它當成關聯式 SQL。它不是。PartiQL 是 一層架在 DynamoDB 既有操作之上的 SQL 相容介面,而不是一個能 join、grouping 或彙總的查詢引擎。那些熟悉的關鍵字,藏著一台底層截然不同的機器。

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(一個項目)

沒有任何規劃器能從兩張資料表讀取、建立雜湊 join,或把多列摺疊 成一個 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 無法 join、grouping 或彙總。

差別在哪——逐項功能比較

只要 Workbench 那一欄標 而 PartiQL 標 ,那就是 DynoTable 的 SQL 補上的缺口。Workbench 透過 DynamoDB 真正的查詢執行環境把你的資料表具體化(materialize),並在其上執行真正的 SQL—— 在 DynamoDB 的存取模式規則之內的 SQL。

功能標準 SQLDynamoDB PartiQLDynoTable Workbench
JOIN … ON …是——INNER / LEFT(對 PK 或 GSI 分割區索引鍵)
RIGHT / FULL / CROSS / 逗號 join
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-vs-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 自家的 model-query 自動修正之所以存在, 正是因為便宜的模型可靠地會產出這些模式:它會剝掉 雙重跳脫的引號,把 LIKE '%x%' 改寫成 containsIS NULL 改寫成 attribute_not_exists,並把內嵌的 LIMIT 提升到請求參數。如果你的 AI 產出的「PartiQL」讀起來像 Postgres,那就是破綻所在。

每張卡片都會顯示關聯式開發者慣用的 SQL、DynamoDB PartiQL 實際會對它做什麼,以及原因。標示「可在 DynoTable 執行」的卡片會顯示 Workbench 能執行的等效 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 跑不了的查詢

當你真的需要 JOINGROUP BY 時,DynoTable 的 SQL Workbench 就是 答案。它會把每個 JOIN 的目標端驗證為一個分割區索引鍵,透過 DynamoDB 真正的 Query/Scan 執行環境把 join 後的列具體化,然後在其上執行單一個 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 / 逗號 join。
  • 尚未支援 self-join,沒有子查詢,沒有衍生資料表,沒有視窗函式。
  • Join 與投影都在純量屬性上運作。

如果你只是需要為原生 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 的操作。它沒有 join、 彙總、子查詢或 GROUP BY

DynamoDB 的 PartiQL 能做 JOIN 嗎? 不能。DynamoDB 的 PartiQL 無法 join 資料表。DynoTable 的 SQL Workbench 可以透過 DynamoDB 真正的查詢執行環境把資料具體化,執行 INNER/LEFT JOIN(對分割區索引鍵或 GSI 分割區索引鍵)。

DynamoDB 的 PartiQL 支援 GROUP BY 或 COUNT 嗎? 不支援——DynamoDB 的 PartiQL 中沒有彙總或 GROUP BYCOUNT/SUM/AVG/GROUP BY/HAVING 的查詢請用 DynoTable 的 SQL Workbench。

為什麼我的 SELECT * 這麼貴? WHERE 中沒有分割區索引鍵時,PartiQL 會跑一次全表 Scan,並在過濾套用之前就把 每個讀出來的項目都計費。加上一個分割區索引鍵述語,把它變成 一次 Query

在 PartiQL 中我該用單引號還是雙引號? 字串值用單引號('CUSTOMER#42'),像資料表和屬性名稱這類識別符 用雙引號("AppData")。用雙引號括住一個值是最 常見的 PartiQL 錯誤。

準備好對 DynamoDB 執行真正的 SQL 了嗎?下載 DynoTable 並開啟一個 Workbench 分頁。

已更新