はじめに
2026 年 6 月 8 日、Amazon Aurora DSQL が JSONB データ型 をサポートしました!
DSQL はサーバーレスの分散 SQL データベースで、PostgreSQL 互換性を持ちますが、今回 JSONB が使えるようになったことで、柔軟なスキーマを持つデータも DSQL で管理できるようになりました。
この記事では AWS CDK(TypeScript)で DSQL クラスタを作成し、実際に JSONB テーブルを作って INSERT / SELECT まで試してみます!
また私自身が JSONB 型をあまり知らなかったので、JSONB の内容含めて解説します。
この記事で学べること
- JSONB と JSON の違い
- JSONB テーブルを作成して INSERT / SELECT を試す手順
-
->,->>,@>といった JSONB 演算子の使い方
前提知識・条件
- 検証日: 2026 年 6 月 12 日
- リージョン:
ap-northeast-1(東京)
JSONB とは?
まず JSON とは
JSON(JavaScript Object Notation)は、構造化されたデータをテキスト形式で表現するフォーマットです。
API のレスポンスや設定ファイルなど、日常的にあちこちで使われていますね。
{
"method": "POST",
"path": "/users",
"status": 201,
"duration_ms": 45
}
PostgreSQL における JSON と JSONB の違い
PostgreSQL には JSON と JSONB の 2 種類の型があります。
| 項目 | JSON | JSONB |
|---|---|---|
| 保存形式 | テキストそのまま | バイナリ(分解済み) |
| 空白・キー順 | 保持する | 保持しない |
| 重複キー | 全て保持 | 最後の値が勝つ |
| 書き込み速度 | 速い | やや遅い(変換コストあり) |
| 読み取り・クエリ速度 | 毎回パースが必要 | 高速 |
| インデックス(GIN 等) | 使えない | 使える |
JSONB は書き込み時に変換コストがかかりますが、読み取りとクエリ速度で有利です。
「スキーマが決まっていない柔軟なデータを格納しつつ、頻繁に検索したい」という場面でよく使われるみたいです。
なお、上の表は一般的な PostgreSQL の話です。
Aurora DSQL では現時点で JSONB カラムへの GIN インデックスは非対応になっています。詳しくは「まとめ」の制限事項をご覧ください。
DSQL での JSONB 圧縮
今回のアップデートでは、圧縮がデフォルトで有効になっていますが、INSERT / UPDATE のタイミングで自動的に圧縮されるので、意識せずにストレージ効率が上がります。
Aurora DSQL は json 列に自動的に圧縮を適用し、デフォルトでは INSERT および UPDATE オペレーション中に大きな json 値を圧縮します。1 MiB の制限は圧縮後のサイズに適用されるため、1 MiB を大幅に超える json 値でも、圧縮後のサイズが制限値未満であれば保存できます。
圧縮を無効にしたい場合は STORAGE キーワードで制御できます。
ALTER TABLE events ALTER COLUMN payload SET STORAGE EXTERNAL;
やってみた
では、実際に動作確認してみます。
今回使うものは次のとおりです。
- AWS CDK(TypeScript): DSQL クラスタの作成
- AWS マネジメントコンソール(クエリエディタ): SQL の実行
Step 1. CDK で DSQL クラスタを作る
CDK プロジェクトを TypeScript で用意します。
スタックの定義はシンプルです。
import * as cdk from 'aws-cdk-lib/core';
import * as dsql from 'aws-cdk-lib/aws-dsql';
import type { Construct } from 'constructs';
export class DsqlJsonbStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const cluster = new dsql.CfnCluster(this, 'DsqlCluster', {
deletionProtectionEnabled: false,
tags: [
{ key: 'Name', value: 'dsql-jsonb-cluster' },
{ key: 'Project', value: 'dsql-supports-jsonb' },
],
});
new cdk.CfnOutput(this, 'ClusterIdentifier', {
value: cluster.attrIdentifier,
description: 'Aurora DSQL クラスタの識別子',
});
new cdk.CfnOutput(this, 'ClusterEndpoint', {
value: cluster.attrEndpoint,
description: 'Aurora DSQL クラスタのエンドポイント',
});
}
}
Step 2. DSQL へ接続
AWS マネジメントコンソールから Aurora DSQL のクラスタ一覧を開き、作成したクラスタを選択します。「クエリエディタ」タブからそのまま SQL を実行できます。
「接続」から対象のクラスタを選ぶだけです。
Step 3. JSONB テーブルを作成
クエリエディタで CREATE TABLE を実行します。payload カラムに JSONB 型を指定するだけで、圧縮は自動的に有効になります。
CREATE TABLE events (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
event_type TEXT NOT NULL,
payload JSONB NOT NULL,
created_at TIMESTAMPTZ DEFAULT now()
);
Step 4. データを INSERT / SELECT
データを INSERT する
API リクエストログ、設定変更、エラーといった種類の異なるイベントをまとめて INSERT してみます。スキーマが違っても JSONB なので全部同じカラムに入るのが便利ですね。
INSERT INTO events (event_type, payload) VALUES
('api_request', '{"method": "POST", "path": "/users", "status": 201, "duration_ms": 45}'),
('api_request', '{"method": "GET", "path": "/orders", "status": 200, "duration_ms": 120}'),
('config_change', '{"key": "feature_flag", "old_value": false, "new_value": true, "changed_by": "admin"}'),
('error', '{"code": "TIMEOUT", "service": "payment", "retry_count": 3, "details": {"endpoint": "/charge", "timeout_ms": 5000}}');
全件取得
まず全件 SELECT してみます。
SELECT * FROM events;
payloadは [object Object] となっており、内容は見れなみたいですね。
->> 演算子でフィールドをテキストとして取得
->> は JSONB のフィールドをテキストとして取得する演算子です。
SELECT
event_type,
payload->>'method' AS method,
payload->>'path' AS path,
(payload->>'duration_ms')::int AS duration_ms
FROM events
WHERE event_type = 'api_request';
結果はこんな感じになります。
| event_type | method | path | duration_ms |
|---|---|---|---|
| api_request | POST | /users | 45 |
| api_request | GET | /orders | 120 |
@> 演算子で包含検索
@> は「左辺が右辺の JSONB を含むか」を検索する演算子です。status: 200 のレコードだけを絞り込んでみます。
SELECT * FROM events
WHERE payload @> '{"status": 200}';
status キーを持つレコードは api_request の 2 件だけですが、 値が 200 のデータは1重圏のみですので、"status": 200 の 1 件だけ返ってきます。
ネストしたフィールドへのアクセス
-> を連続させることでネストしたフィールドにアクセスできます。
SELECT
payload->'details'->>'endpoint' AS endpoint,
payload->'details'->>'timeout_ms' AS timeout_ms
FROM events
WHERE event_type = 'error';
error レコードの details オブジェクト内の値が取れました。
| endpoint | timeout_ms |
|---|---|
| /charge | 5000 |
まとめ
CDK で Aurora DSQL クラスタを作り、JSONB テーブルへのデータ操作まで試してみました。
- JSONB カラムの定義はただ型を
JSONBにするだけ。圧縮は自動なので意識しなくていい -
->,->>,@>などの PostgreSQL 演算子がそのまま動く - スキーマの違うイベントを 1 つのテーブルで管理できるのは柔軟で便利!
JSONB が使えることで、「ログ系データは別サービスで管理してたけど DSQL に統合できそう」みたいなユースケースが広がった印象です。Aurora DSQL はサーバーレスで運用負荷がほぼゼロなので、こういう用途と相性がいいかなと感じています。
なお、簡単な動作確認時には気になりませんでしたが、ドキュメントで確認した制限事項も最後に記載しておきます。
制限事項
- JSONB の最大サイズは 1 MiB(圧縮後)
- PostgreSQL の JSON 関数・演算子はすべてサポート
-
json_populate_record/jsonb_populate_recordset等はカスタム複合型(CREATE TYPE)では未対応。テーブル/ビューの行型でのみ動作する模様 - JSONB カラムへの GIN インデックスは現時点では非対応
この記事が誰かのお役に立てると幸いです、最後まで読んでいただきありがとうございました!!






