入門閱讀時間 5 分鐘

DynamoDB PartiQL vs SQL:差異何在(以及哪些會出錯)

使用 DynamoDB PartiQL 時最大的混淆來源——對人類和 AI 助理皆然——就是把它當成關聯式 SQL。它不是。PartiQL 是覆蓋在 DynamoDB 既有操作之上的相容 SQL 的介面,而不是能做 join、grouping 或聚合的查詢引擎。那些熟悉的關鍵字底下藏著一台截然不同的機器。

心智模型

每一條 PartiQL 語句最終都會編譯成 DynamoDB 的某個原生操作:

你寫的DynamoDB 執行的
SELECT … WHERE PK = …GetItemQuery
SELECT …(無 PK)Scan(讀取整張表
INSERT INTO …PutItem
UPDATE … WHERE PK=… AND SK=…UpdateItem(單一 item)
DELETE … WHERE PK=… AND SK=…DeleteItem(單一 item)

沒有任何規劃器能從兩張表讀取、建立 hash 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 或聚合。

差異何在——逐項功能比較

每個 DynoTable 的 SQL Workbench 執行的 都會標記出來。Workbench 透過 DynamoDB 真實的查詢執行環境物化你的表格,再於其上執行真正的 SQL——在 DynamoDB 的存取模式規則之內的 SQL。

功能標準 SQLDynamoDB PartiQLDynoTable Workbench
JOIN … ON … INNER / LEFT(對 PK 或 GSI partition key)
RIGHT / FULL / CROSS / 逗號 join
自我 join(尚未支援)
子查詢 / 衍生表
CTE(WITH …
UNION / INTERSECT / EXCEPT
GROUP BY / HAVING
聚合函式(COUNT/SUM/AVG/MIN/MAX
DISTINCT
CASE / CAST
視窗函式
ORDER BY 任意欄位 僅 sort key(需 partition-key 的 WHERE 任意欄位
LIMIT 內嵌(改用請求的 limit 參數)
LIKE(改用 contains / begins_with
IS NULL / IS NOT NULL(改用 attribute_not_exists / attribute_exists
無 PK 的 SELECT *scan 靜默的整表 Scan(附帶成本可視性)

哪些會出錯,以及為什麼

這些是 DynoTable 的 PartiQL 驗證器在查詢送上線之前就會標示的失敗——每一個都可追溯到真實的 DynamoDB 限制。

  • 無 partition key 的 SELECT * 是一個隱藏的 Scan PartiQL 不會報錯;它只是讀取每一個 item 然後事後過濾,這正是友善語法背後經典的 Query vs Scan 成本陷阱。
  • UPDATE / DELETE 需要完整的主鍵。 它們對應到單一 item 的 UpdateItem/DeleteItem,所以 WHERE 必須鎖定 partition key(在複合鍵的表上還要 sort key)。你無法用一條語句「更新所有 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 就是答案。它會針對 partition key 驗證每個 JOIN 的對接側,透過 DynamoDB 真實的 Query/Scan 執行環境物化被 join 的列,再於其上執行你完整的 SQL(聚合函式、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 的對接屬性必須是 partition key 或 GSI partition key。沒有 RIGHT / FULL / CROSS / 逗號 join。
  • 尚不支援自我 join,沒有子查詢、沒有衍生表、沒有視窗函式。
  • Join 和投影作用於純量屬性。

如果你只需要為原始 API 組合條件與鍵運算式,DynamoDB Expression Builder 完全不必經過 PartiQL 介面,就能產生正確的 FilterExpression / KeyConditionExpression。想看 PartiQL 的正確寫法,請參考實作過的 PartiQL 範例;想衡量任何查詢的成本,請使用 item 大小計算器。注意 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(對 partition key 或 GSI partition key)。

DynamoDB PartiQL 支援 GROUP BY 或 COUNT 嗎? 不支援——DynamoDB PartiQL 裡沒有聚合函式或 GROUP BYCOUNT/SUM/AVG/GROUP BY/HAVING 查詢請改用 DynoTable 的 SQL Workbench。

為什麼我的 SELECT * 成本這麼高? WHERE 中沒有 partition key 時,PartiQL 會執行整表 Scan,並在過濾套用之前就計量每一個讀取的 item。加上一個 partition-key 述詞,把它變成 Query

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

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

已更新