DynamoDB のための SQL: 何が動き、何が動かず、そして Workbench
DynamoDB は NoSQL のキーバリューストアですが、人々が予想する以上に SQL 風の質問に
答え — そして期待するよりはるかに少なく答えます。これは正直な地図です。DynamoDB 上の
SQL として実際に標準で得られるもの、それがどこで止まるのか、そしてネイティブの表層が
表現できない JOIN / GROUP BY / 集計クエリを実行する数少ない方法です。
DynamoDB を SQL でクエリできる? 短い答え
部分的に。DynamoDB は PartiQL を搭載しており、
AWS ドキュメントは
これを「Amazon DynamoDB のデータを選択、挿入、更新、削除するための SQL 互換の
クエリ言語」と説明しています。つまり SELECT * FROM "Orders" WHERE OrderID = 100 と
書けて、動きます。
しかし PartiQL は DynamoDB API の上にある SQL 互換の表層 であって、SQL エンジン
ではありません。構文は話しますが、リレーショナルなクエリ能力を 追加しません。AWS は
「Amazon DynamoDB は PartiQL クエリ言語の サブセット をサポートする」と明言しています
(リファレンス)。
JOIN、GROUP BY、COUNT(*) に手を伸ばした瞬間、PartiQL ができることの外側にいます —
機能ごとの完全な比較は PartiQL vs SQL を参照してください。
PartiQL: SQL 互換の表層であって SQL エンジンではない
PartiQL は SQL 風に見える文を、SDK が公開するのと同じデータプレーン操作にマッピング
します。パーティションキーの等価性を持つ SELECT は Query にコンパイルされ、それが
ない SELECT は Scan にコンパイルされます。
AWS の SELECT リファレンスより:
WHERE 句でパーティションキーとの等価条件または IN 条件が提供されない場合、
SELECT文はフルテーブルスキャンになり得ます。
つまり Query と Scan を支配するのと同じアクセスパターンのルールが依然として適用
されます — PartiQL はそれらを見慣れた構文の裏に隠すだけです。クエリプランナーも、結合も、
集合ベースの集計も追加しません。すべての文は 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 アイテム) |
操作が単一の Get/Query/Scan/Put/Update/Delete に還元されなければ、PartiQL はそれを 表現できません。以下のすべては、その 1 つの事実の帰結です。
PartiQL がカバーするもの
DynamoDB の PartiQL は 4 つの DML / クエリ文をサポートします。
- SELECT — アイテムを読む(
QueryまたはScanにコンパイル) - INSERT — アイテムを追加(
PutItem) - UPDATE — アイテムを変更(
UpdateItem) - DELETE — アイテムを削除(
DeleteItem)
また
トランザクションとバッチ操作も
サポートします。整形された読み取りは、等価性または IN でパーティションキーを対象に
します。
SELECT OrderID, Total
FROM "Orders"
WHERE OrderID IN [1, 2, 3] ORDER BY OrderID DESCORDER BY は許可されますが、AWS リファレンスは順序付けキーを「ハッシュキーまたは
ソートキー」 — パーティションキーまたはソートキーであり、任意の列ではない — に制限
します。それが PartiQL の SELECT が受け入れるものの天井です。コピペできる文については
PartiQL の例を参照してください。
PartiQL にできないこと
これらは開発者が「SQL」に最もよく期待するもので、PartiQL はその どれも サポート しません。
JOINなし。 PartiQL のSELECT構文は 単一のFROM {{table}}[.{{index}}]です — 1 つのテーブルまたは 1 つのインデックスで あり、キーで関連付けた 2 つのテーブルではありません。これは シングルテーブル設計のトレードオフです。クエリ層が後で データを再形成できないので、アクセスパターンに合わせて事前にモデリングします。GROUP BYなし。 文法にありません。行をグループ化する句はありません。- 集計関数なし。
PartiQL 関数リファレンスは
「集計関数」の下にちょうど 1 つの関数を挙げています:
SIZE、これは 単一 アイテムの 属性のバイトサイズを返します。行をまたぐCOUNT、SUM、AVG、MIN、MAXはありません。 AWS は端的に述べています: 「このリストに含まれない SQL 関数は、現在 DynamoDB では サポートされていない。」 LIKEなし、サブクエリなし、UNIONなし、ウィンドウ関数なし。 パターンマッチングはcontains/begins_withを使い、残りには同等のものがまったくありません。
そのため「先月の顧客ごとの総売上」 — どんなリレーショナルデータベースでも 1 行の
GROUP BY — は PartiQL では表現できません。データをスキャンで取り出して、アプリケーション
コードで集計することになります。
DynamoDB データに対して本物の JOIN / GROUP BY / 集計の振る舞いを得る唯一の方法は、
その上で 実際の SQL エンジン を実行するツールです。2 つあります: Amazon Athena の
フェデレーテッドコネクタと、DynoTable の SQL Workbench です。
Amazon Athena 経由で DynamoDB を本物の SQL でクエリする方法
「DynamoDB 上の本物の SQL」への AWS 自身の答えは
Amazon Athena DynamoDB コネクタで、
「Amazon Athena が DynamoDB と通信できるようにし、テーブルを SQL でクエリできるように
する」ものです。Athena は完全な SQL エンジンなので、これは JOIN と集計を 実際に
得られます — AWS の手順は「Athena を使って Amazon DynamoDB テーブルにアクセス、
クエリ、結合する」と
題されています。
落とし穴はセットアップとコストです。
- アカウントにデプロイする Lambda ベースのフェデレーテッドコネクタ です(Athena コンソールまたは Serverless Application Repository 経由)。スキーマには AWS Glue を 通して接続し、結果は S3 バケットにスピルします (コネクタドキュメント)。
- 内部では依然として DynamoDB の
QueryとScanAPI 操作を使います。AWS は「スキャンを 使うクエリは大量の読み取りキャパシティユニット(RCU)を消費し得る」と警告しているので、 大きなテーブルに対する分析クエリは多くのアイテムを読み取り — そして課金します (コネクタのコスト)。 スキャンの多いクエリのコストを測るには アイテムサイズ計算機を使ってください。 INSERT INTOのような書き込み操作はコネクタ経由ではサポートされません。
Athena はスケジュールされた分析や BI ダッシュボードに適したツールです。「2 つのテーブルを 結合して結果を目で見たいだけ」という日常的なケースには重すぎます — それが次のセクションが 埋めるギャップです。
DynoTable SQL Workbench: DynamoDB のアクセスパターンのルール内での SQL
DynoTable の SQL Workbench は、Lambda、Glue、S3 を立ち上げることなく、デスクトップ
クライアントからライブの DynamoDB テーブルに対して本物の SQL — JOIN、GROUP BY、
COUNT/SUM/AVG — を実行します。DynamoDB の本物の Query/Scan ランタイムを通して
行をマテリアライズし、その上でインメモリエンジンで完全な SQL を実行します。
-- DynoTable Workbench で実行(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「DynamoDB のアクセスパターンのルール内で」という部分が重要です。Workbench は DynamoDB が
Postgres であるふりをしません — 内部では依然として Query/Scan を通して読み取るので、
各クエリのコストを意識し続けられ、DynamoDB のアクセスモデルを隠すのではなく強制します。
INNER JOINとLEFT JOINのみ —ONの対象属性はパーティションキーまたは GSI パーティションキーでなければなりません。RIGHT/FULL/CROSS/ カンマ結合はありません。- 自己結合はまだなし、サブクエリなし、派生テーブルなし、ウィンドウ関数なし。
- 結合と射影はスカラー属性に対して動作します。
生の API のための条件とキー式を組み立てるだけ — 完全な SQL 文ではなく — でよいなら、
DynamoDB 式ビルダーが PartiQL の表層なしで正しい
FilterExpression / KeyConditionExpression を生成します。
テーブルを探索、デバッグ、分析するための DynamoDB SQL クライアント が目標なら、 Workbench がそのギャップを埋めます — そして DynoTable の残りはその周りの完全な DynamoDB GUI です。
自分のテーブルに対して本物の SQL を実行するには DynoTable を試してください。
FAQ
DynamoDB で SQL を実行できる? PartiQL(キーで SELECT/INSERT/UPDATE/DELETE する SQL 互換のサブセット)を実行できます。 完全な SQL — JOIN、GROUP BY、集計 — には、その上に SQL エンジンが必要です: Amazon Athena DynamoDB コネクタ、または DynoTable の SQL Workbench。
DynamoDB PartiQL は JOIN をサポートしている?
いいえ。PartiQL の SELECT 構文は単一の FROM テーブルまたはインデックスを持ち、結合
文法はありません。結合には DynamoDB の上に重ねたエンジンが必要です。
PartiQL は GROUP BY や COUNT、SUM のような集計をサポートしている?
いいえ。GROUP BY 句はなく、唯一の「集計」関数は SIZE(1 アイテムの属性のバイトサイズ)
です。行をまたぐ COUNT、SUM、AVG、MIN、MAX はサポートされません。
DynamoDB は SQL それとも NoSQL? NoSQL — キーバリュー・ドキュメントストアです。PartiQL がその上に SQL 互換のクエリ言語を 追加しますが、DynamoDB にはリレーショナルエンジン、結合、集計はありません。
PartiQL はアドホッククエリに向いている?
キーベースの検索には、はい。分析的なアドホッククエリ(カウント、ロールアップ、結合)には、
いいえ — PartiQL はそれらを表現できず、制約のない SELECT は黙ってフルテーブルスキャンに
なります。
JOIN や GROUP BY を扱う DynamoDB SQL クライアントはある?
はい — DynoTable の SQL Workbench はデスクトップからライブテーブルに対して JOIN/
GROUP BY/集計を実行し、Amazon Athena は AWS アカウントにデプロイするフェデレーテッド
コネクタ経由でそれを行います。