DynamoDB の PartiQL vs SQL: 何が違うか(そして何が壊れるか)
DynamoDB の PartiQL における最大の混乱の原因は — 人間にとっても AI アシスタントにとっても — それをリレーショナル SQL として扱ってしまうことだ。だが PartiQL はそうではない。PartiQL は DynamoDB の既存オペレーションの上に乗った SQL 互換のサーフェス であって、結合・グループ化・集計ができるクエリエンジンではない。見慣れたキーワードの裏には、まったく異なる仕組みが隠れている。
メンタルモデル
すべての PartiQL ステートメントは、DynamoDB のネイティブオペレーションのいずれか 1 つにコンパイルされる:
| 書くもの | DynamoDB が実行するもの |
|---|---|
SELECT … WHERE PK = … | GetItem または Query |
SELECT … (PK なし) | Scan (テーブル全体を読む) |
INSERT INTO … | PutItem |
UPDATE … WHERE PK=… AND SK=… | UpdateItem (1 アイテム) |
DELETE … WHERE PK=… AND SK=… | DeleteItem (1 アイテム) |
2 つのテーブルから読んだり、ハッシュ結合を組んだり、行を COUNT に畳み込んだりできるプランナは存在しない。あるオペレーションが単一の Get/Query/Scan/Put/Update/Delete にマップされなければ、PartiQL はそれを表現できない。これがすべてだ — 以下のすべては、この 1 つの事実の帰結にすぎない。
同じマッピングをフローとして見ると — WHERE 句が、SELECT を安価な Query にするか、テーブル全体の Scan にするかを決める:
各ステートメントはちょうど 1 つのネイティブオペレーションに解決される — その 1 対 1 のマッピングこそが、PartiQL が結合・グループ化・集計をできない理由だ。
何が違うか — 機能ごとに
DynoTable の SQL Workbench が 実行できる にはそれぞれ印が付けてある。Workbench はあなたのテーブルを DynamoDB の本物のクエリランタイムを通してマテリアライズし、その上で本物の SQL を実行する — DynamoDB のアクセスパターンの規則の中での SQL。
| 機能 | 標準 SQL | DynamoDB の PartiQL | DynoTable の Workbench |
|---|---|---|---|
JOIN … ON … | INNER / LEFT (PK または GSI パーティションキーへ) | ||
RIGHT / FULL / CROSS / カンマ結合 | |||
| 自己結合 | (まだ非対応) | ||
| サブクエリ / 派生テーブル | |||
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 | (attribute_not_exists / attribute_exists を使う) | ||
PK なしの SELECT * | スキャンする | 暗黙のテーブル全体 Scan | (コスト可視化付き) |
何が壊れるか、そしてなぜ
これらは、クエリがワイヤに届く前に DynoTable の PartiQL バリデータが指摘する失敗であり — それぞれが本物の DynamoDB の制約に由来する。
- パーティションキーのない
SELECT *は隠れたScan。 PartiQL はエラーにしない。ただ全アイテムを読み、その後でフィルタするだけだ。これは親しみやすい構文の裏に潜む、典型的な Query vs Scan のコストの落とし穴だ。 UPDATE/DELETEは完全なプライマリキーを必要とする。 これらは単一アイテムのUpdateItem/DeleteItemにマップされるので、WHEREがパーティションキー(そして複合キーテーブルならソートキーも)を確定させなければならない。「status = 'open' のすべての行を更新」を 1 ステートメントで行うことはできない。- 二重引用符は識別子であって文字列ではない。 DynamoDB の PartiQL はここで SQL 標準に従う:
"name"は列名/テーブル名で、'name'は文字列値だ。値を二重引用符で囲むのは最もよくある初心者のミスで — バリデータのメッセージは文字どおり 「二重引用符は DynamoDB の PartiQL では識別子を区切るものであって文字列ではありません。文字列値には単一引用符を使ってください。」 となっている。 INは丸括弧ではなく角括弧を使う:WHERE pk IN ['a','b']。PK 値 50 個 / 非キー値 100 個が上限。JOINなし、集計なし。 テーブルを結合したり行を畳み込んだりするエンジンが存在しない。これは シングルテーブル設計 のトレードオフだ: クエリ層が後からデータを再形成できないため、事前にアクセスパターンに合わせてモデリングする。
なぜ AI アシスタントはこれを間違えるのか
LLM はリレーショナル SQL の大海で訓練されているため、DynamoDB に対して JOIN・GROUP BY・LIKE・インラインの LIMIT・二重引用符の文字列リテラルを自信たっぷりに吐き出す — そのどれもを DynamoDB は拒否する。DynoTable 独自のモデルクエリ自動修正が存在するのは、まさに安価なモデルがこうしたパターンを確実に生成するからだ: 二重エスケープされた引用符を取り除き、LIKE '%x%' → contains、IS NULL → attribute_not_exists に書き換え、インラインの LIMIT をリクエストパラメータに引き上げる。あなたの AI が Postgres のように読める「PartiQL」を生成しているなら、それが見分けるサインだ。
DynoTable の SQL Workbench: PartiQL では実行できないクエリ
本当に JOIN や GROUP BY が必要なとき、DynoTable の SQL Workbench が答えになる。各 JOIN の結合先をパーティションキーに照らして検証し、結合された行を DynamoDB の本物の Query/Scan ランタイムを通してマテリアライズし、その上であなたの完全な 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の結合先属性はパーティションキーまたは GSI パーティションキーでなければならない。RIGHT/FULL/CROSS/ カンマ結合はなし。- 自己結合はまだなし、サブクエリなし、派生テーブルなし、ウィンドウ関数なし。
- 結合と射影はスカラー属性に対して動作する。
生の API のために条件とキー式を組み立てるだけでよいなら、DynamoDB Expression Builder が PartiQL のサーフェスをまったく介さずに正しい FilterExpression / KeyConditionExpression を生成する。PartiQL を正しく行うには、実例付きの PartiQL の例 を参照。任意のクエリのコストを見積もるには、アイテムサイズ計算ツール を使う。なお PartiQL はワイヤフォーマットを変えることはなく — 値は依然として DynamoDB-JSON として送られる。クライアント選びに迷う? Workbench が 素の DynamoDB GUI や Dynobase に対してどう位置づけられるかを参照。
FAQ
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 タブを開いてください。