DynamoDB PartiQL vs SQL:差異何在(以及哪些會出錯)
使用 DynamoDB PartiQL 時最大的混淆來源——對人類和 AI 助理皆然——就是把它當成關聯式 SQL。它不是。PartiQL 是覆蓋在 DynamoDB 既有操作之上的相容 SQL 的介面,而不是能做 join、grouping 或聚合的查詢引擎。那些熟悉的關鍵字底下藏著一台截然不同的機器。
心智模型
每一條 PartiQL 語句最終都會編譯成 DynamoDB 的某個原生操作:
| 你寫的 | DynamoDB 執行的 |
|---|---|
SELECT … WHERE PK = … | GetItem 或 Query |
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:
每一條語句都恰好解析成一個原生操作——正是這種一對一的對應,使得 PartiQL 無法 join、grouping 或聚合。
差異何在——逐項功能比較
每個 DynoTable 的 SQL Workbench 能 執行的 都會標記出來。Workbench 透過 DynamoDB 真實的查詢執行環境物化你的表格,再於其上執行真正的 SQL——在 DynamoDB 的存取模式規則之內的 SQL。
| 功能 | 標準 SQL | DynamoDB PartiQL | DynoTable 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 產出 JOIN、GROUP BY、LIKE、內嵌 LIMIT 和雙引號字串字面值——而 DynamoDB 全部都會拒絕。DynoTable 自家的 model-query 自動修正之所以存在,正是因為便宜的模型可靠地會產生這些模式:它會剝除雙重轉義的引號,把 LIKE '%x%' 改寫成 contains、IS NULL 改寫成 attribute_not_exists,並把內嵌的 LIMIT 提升為請求參數。如果你的 AI 產出的「PartiQL」讀起來像 Postgres,那就是線索。
DynoTable 的 SQL Workbench:PartiQL 跑不動的查詢
當你真的需要 JOIN 或 GROUP BY 時,DynoTable 的 SQL Workbench 就是答案。它會針對 partition key 驗證每個 JOIN 的對接側,透過 DynamoDB 真實的 Query/Scan 執行環境物化被 join 的列,再於其上執行你完整的 SQL(聚合函式、GROUP BY、DISTINCT、CASE、CAST)——在 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 JOIN和LEFT 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 GUI 或 Dynobase 的定位。
常見問答
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 BY。COUNT/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 分頁。