Skip to main content
Copyright © 2015 NTT DATA Corporation
2015年6月26日
株式会社 NTTデータ
JSONBはPostgreSQL9.5でいかに改善されたのか?
今後の展望は?
MyNA・JPUG合同DB勉強会 in 東京
2Copyright © 2015 NTT DATA Corporation
PostgreSQL エバンジェリスト@ NTT データ
社内 PostgreSQL 営業・技術支援
GresCube 開発・サポート
PostgreSQL コミッタ
全世界で20名、日本人で3人目
PostgreSQL のコア機能を開発
レプリケーション(非同期 / 同期 / カスケード)
トランザクションログ圧縮
pg_bigm(全文検索モジュール)
藤井 雅雄 @fujii_masao
3Copyright © 2015 NTT DATA Corporation
PostgreSQL 開発者@ NTT データ
社内 PostgreSQL 営業・技術支援
GresCube 開発・サポート
PostgreSQL のコア機能を開発
レプリケーション運用性向上
REINDEX SCHEMA / VERBOSE
pgbench(ベンチマークツール)の改善
pg_bigm(全文検索モジュール)
コア機能へのパッチレビューア
澤田 雅彦 @sawada_masahiko
4Copyright © 2015 NTT DATA Corporation
本日は
Event Title
Tutorial NoSQL on ACID
Talk
Update and Delete operations for jsonb
Rethinking JSONB
Unconference Direction of json and jsonb
PGConで話題となったJSONB型の新機能や今後の展望についてご紹介
5Copyright © 2015 NTT DATA Corporation
INDEX
PostgreSQLがサポートするNoSQL機能の振り返り
次期メジャーバージョン9.5でのJSONB型の新機能
JSONB型の今後の開発展望について
Copyright © 2015 NTT DATA Corporation 6
PostgreSQLがサポートするNoSQL機能の振り返り
7Copyright © 2015 NTT DATA Corporation
PostgreSQLでできるNoSQLっぽいこと
XML (8.2~)
hstore (8.2~)
JSON (9.2~)
JSONB (9.4~)
FDWで連携 (8.4~)
<foo bar=‘abc’>hoge</foo>
“foo” => “bar”
{“abc” : “foo”}
mongo_fdw,
redis_fdw
PostgreSQLでは様々な方法で半構造化データを取り扱い可能
8Copyright © 2015 NTT DATA Corporation
PostgreSQLにおけるJSON
JSONデータ
{
"id":1,
"name":"鈴木",
"address":"東京",
"birth_day":"1970-01-01“
}
CREATE TABLE tbl (
data JSON);
key value
PostgreSQLではJSONデータを専用データ型に格納可能
9Copyright © 2015 NTT DATA Corporation
PostgreSQLにおけるJSON
CREATE TABLE hoge (data JSON);
INSERT INTO hoge VALUES ('
{"name" : "PostgreSQL",
"type" : "DBMS",
"developer" :
[{"name" : "Sawada", "age" : "25"},
{"name" : "Fujii", "age" : "55"}]}
');
SELECT data->'type',
((data->'developer')->1)->'name' FROM hoge;
?column? | ?column?
----------+----------
"DBMS" | "Fujii"
(1 row)
1Copyright © 2015 NTT DATA Corporation
PostgreSQLにおけるJSONの歴史
v9.2 (2012年) v9.3 (2013年) v9.4 (2014年) v9.5
TEXT型 + 構文チェッカ
利用可能な関数と演算子
はわずか
演算子4個追加
要素抽出の演算子(->)
関数10個追加
JSONから行への変換
バイナリ形式 + 構文チェッカ
GINインデックス対応
JSON型
サポート
JSONB型
サポート !?
関数と演算子の
充実化
1Copyright © 2015 NTT DATA Corporation
JSON型とJSONB型の比較
JSON型 JSONB型
利用可能
バージョン
9.2以降 9.4以降
格納方式
テキスト形式
データをそのままの形で格納
バイナリ形式
不要な空白の削除、重複キーの除去、
バイナリ変換を行った上で格納
インデックス
Btree式インデックス Btree式インデックス
GIN
利用可能な
演算子
要素抽出の演算子のみ 要素抽出に加えて、比較・包含の演算子
検索性能
低速
検索時にテキストのパースが必要
GIN未対応
高速
パース不要
GIN対応済
更新性能
高速
格納時のオーバーヘッドが小さい
低速
格納時のオーバーヘッドが大きい
1Copyright © 2015 NTT DATA Corporation
JSONBのGINインデックス
作成可能なGINインデックスは2種類
デフォルト
CREATE INDEX idx ON hoge USING gin (data);
jsonb_path_ops
CREATE INDEX idx ON hoge USING gin (data jsonb_path_ops);
@> only
Faster
Smaller index
演算子 説明 例
@> 「左辺のJSON」は「右辺のJSON」を包含するか? {"a" : 1, "b" : 2} @> {"b" : 2}
? 右辺のキーが左辺のJSONに存在するか? {"a" : 1, "b" : 2} ? 'b'
?& 右辺のキーのすべてが左辺のJSONに存在するか? {"a" : 1, "b" : 2} ?& ARRAY['b', 'c']
?| 右辺のキーのいずれかが左辺のJSONに存在するか? {"a" : 1, "b" : 2} ?| ARRAY['b', 'c']
1Copyright © 2015 NTT DATA Corporation
JSONB + GIN による強力なインデックス検索
CREATE TABLE employee (data JSONB);
CREATE INDEX employee_idx ON employee USING gin (data jsonb_path_ops);
INSERT INTO employee VALUES
('{"name" : "斉藤", "age" : 27, "role" : "開発"}'),
('{"name" : "田中", "age" : 45, "role" : "営業"}'),
('{"name" : "佐藤", "age" : 33, "role" : "開発"}'),
('{"name" : "山田", "age" : 53, "role" : "経営"}');
SELECT * FROM employee WHERE data @> '{"role" : "開発"}';
QUERY PLAN
----------------------------------------------------------------------------
Bitmap Heap Scan on employee
Recheck Cond: (data @> '{"role": "開発"}'::jsonb)
-> Bitmap Index Scan on employee_idx
Index Cond: (data @> '{"role": "開発"}'::jsonb)
1Copyright © 2015 NTT DATA Corporation
JSONB + GIN による強力なインデックス検索
CREATE TABLE employee (data JSONB);
CREATE INDEX employee_idx ON employee USING gin (data jsonb_path_ops);
INSERT INTO employee VALUES
('{"name" : "斉藤", "age" : 27, "role" : "開発"}'),
('{"name" : "田中", "age" : 45, "role" : "営業"}'),
('{"name" : "佐藤", "age" : 33, "role" : "開発"}'),
('{"name" : "山田", "age" : 53, "role" : "経営"}');
SELECT * FROM employee WHERE data @> '{"name" : "山田"}';
SELECT * FROM employee WHERE data @> '{"age" : 33}';
SELECT * FROM employee WHERE data @> '{"role" : "開発"}';
INSERT INTO employee VALUES
('{"name" : "安田", "age" : 41, "role" : "総務", "office" : "東京"}');
SELECT * FROM employee WHERE data @> '{"office" : "東京"}';
すべてのKeyに対して
インデックス検索可能
新規追加のKeyに
対しても
インデックス検索可能
1Copyright © 2015 NTT DATA Corporation
振り返りのまとめ
v9.2 (2012年) v9.3 (2013年) v9.4 (2014年) v9.5
TEXT型 + 構文チェッカ
利用可能な関数と演算子
はわずか
演算子4個追加
要素抽出の演算子(->)
関数10個追加
JSONから行への変換
バイナリ形式 + 構文チェッカ
GINインデックス対応
JSON型
サポート
JSONB型
サポート !?
関数と演算子の
充実化
Copyright © 2015 NTT DATA Corporation 1
次期メジャーバージョン9.5でのJSONB型の新機能
1Copyright © 2015 NTT DATA Corporation
充実してきたPostgreSQLのJSON(B)型ですが。。
• キーによる値の取り出し (->)
• パスによる値の取り出し (#>)
• 任意のパスのオブジェクトを 追加 (?)
• 〃 を 更新 (?)
• 〃 を 削除 (?)
1Copyright © 2015 NTT DATA Corporation
9.5ではJSONBデータを操作する関数が追加
新規に追加された関数一覧
jsonb_concat() 追加
jsonb_delete() 削除
jsonb_set() 更新
jsonb_pretty() JSONB型を見やすく整形
NEW!
NEW!
NEW!
NEW!
1Copyright © 2015 NTT DATA Corporation
jsonb_concat関数
SELECT jsonb_concat(
'{"a": 1, "b": "hoge"}'::jsonb,
'{"a": 999, "c": [1,2]}'::jsonb
);
jsonb_concat
--------------------------------------
{"a": 999, "b": "hoge", "c": [1, 2]}
(1 row)
2Copyright © 2015 NTT DATA Corporation
jsonb_delete関数
SELECT jsonb_delete(
'{"a": 1, "b": {"c": 999}, "d": [2,3]}'::jsonb,
'a‘
);
jsonb_delete
--------------------------------
{"b": {"c": 999}, "d": [2, 3]}
(1 row)
SELECT jsonb_delete(
'{"a": 1, "b": {"c": 999}, "d": [2,3]}'::jsonb,
'{d, -1}‘
);
jsonb_delete
-------------------------------------
{"a": 1, "b": {"c": 999}, "d": [2]}
(1 row)
2Copyright © 2015 NTT DATA Corporation
jsonb_set関数 (置き換え)
SELECT jsonb_set(
' {"n" : null, "a": {"b": 100}}'::jsonb,
'n',
‘999‘
);
jsonb_set
---------------------------------
{"a": {"b": 100}, "n": 999}
(1 row)
2Copyright © 2015 NTT DATA Corporation
jsonb_set関数 (ネストしたパス指定)
SELECT jsonb_set(
'{"a":{"b": 2}}'::jsonb,
'{a, b}',
'[1,2]‘
);
jsonb_set
----------------------
{"a": {"b": [1, 2]}}
(1 row)
2Copyright © 2015 NTT DATA Corporation
jsonb_set関数 (添字に負の数)
SELECT jsonb_set(
'{"a": {"b": [2,3]}}'::jsonb,
'{a, b, -1}',
'999‘
);
jsonb_set
------------------------
{"a": {"b": [2, 999]}}
(1 row)
2Copyright © 2015 NTT DATA Corporation
jsonb_set関数 (なかったら追加)
SELECT jsonb_set(
' {"n" : null, "a": {"b": 999}}'::jsonb,
'c',
‘999‘,
true
);
jsonb_set
-----------------------------------------
{"a": {"b": 2}, “c": 999, "n": null}
(1 row)
2Copyright © 2015 NTT DATA Corporation
jsonb_pretty関数
SELECT jsonb_pretty('{"a":"hoge", "b":[1,2,3], "c":{"d": 999}}'::jsonb);
jsonb_pretty
------------------
{ +
"a": "hoge", +
"b": [ +
1, +
2, +
3 +
], +
"c": { +
"d": 999 +
} +
}
(1 row)
2Copyright © 2015 NTT DATA Corporation
演算子
JSONB型の演算子一覧
->、 ->> キー指定で要素取得
#>、 #>> パス指定で要素取得
@>、 <@ 包含(JSONBのみ)
?、 ?|、 ?& 存在(JSONBのみ)
-、-# 削除(JSONBのみ)
|| 追加(JSONBのみ)
NEW!
NEW!
JSONBデータを操作する演算子が追加
2Copyright © 2015 NTT DATA Corporation
削除
SELECT '{ "a" : 1, "b" : { "c" : 2 }}'::jsonb - 'b';
delta
-------------
{"a": 1}
SELECT '{ "a" : 1, "b" : { "c" : 2 }}'::jsonb - 'c';
delta
-------------------------
{"a": 1, "b": {"c": 2}}
SELECT '{"a":1, "b":{"c":2}}'::jsonb #- '{b,c}';
delta
---------------------
{"a": 1, "b": {}}
(1 row)
2Copyright © 2015 NTT DATA Corporation
追加
SELECT '{ "a" : 1, "b" : 2}'::jsonb || '{ "c" : 3 }';
concat
--------------------------
{"a": 1, "b": 2, "c": 3}
SELECT '{ "a" : 1, "b" : 2}'::jsonb || '{ "a" : 3 }';
concat
------------------
{"a": 3, "b": 2}
2Copyright © 2015 NTT DATA Corporation
9.5新機能まとめ
関数
演算子
-、-# 削除
|| 追加
jsonb_concat() 追加
jsonb_delete() 削除
jsonb_set() 更新
jsonb_pretty() JSONB型を見やすく整形
NEW!
NEW!
NEW!
NEW!
NEW!
NEW!
Copyright © 2015 NTT DATA Corporation 3
JSONB型の今後の開発展望について
3Copyright © 2015 NTT DATA Corporation
今後のはなし
JSONB型の関数の拡充
次期バージョンにむけてJSONB型の関数の拡充が進行中。
さらなる利便性の向上に期待!
- Update and Delete operations for jsonb -
by Andrew Dunstan at PGCon 2015
3Copyright © 2015 NTT DATA Corporation
今後のはなし
検索機能の向上
JSONB型を使ったクエリは書きにくい?
次期バージョンに向けて改善が進められています!
- Rethinking JSONB -
by Alexander Korotkov, Konstantin Knizhnik, Oleg Bartunov
at PGCon 2015
3Copyright © 2015 NTT DATA Corporation
検索機能の向上
例えば、配列がネストされた複雑なデータの場合。
SELECT jsonb_pretty(
‘{"department": [{"staff": [{"name": “hoge", "title": “chief”}]}]}’
);
jsonb_pretty
-------------------------------------
{ +
"department": [ +
{ +
“staff”: [ +
{ +
"name": “hoge", +
"title": “chief" +
} +
] +
} +
] +
}
3Copyright © 2015 NTT DATA Corporation
検索機能の向上
「name」がhoge、「title」がmanagerまたはchiefのデータを探そうとすると。。
SELECT
*
FROM
company
WHERE
jb->’department’->0->’staff’->0->’name’ = ‘hoge’ AND
(
jb->’department’->0->’staff’->0->’title’ = ‘manager’ OR
jb->’department’->0->’staff’->0->’title’ = ‘chief’
)
SELECT
*
FROM
company
WHERE
(
jb->’department’->0->’staff’->0->’name’ = ‘hoge’ AND
jb->’department’->0->’staff’->0->’title’ = ‘manager’
) OR
(
jb->’department’->0->’staff’->0->’name’ = ‘hoge’ AND
jb->’department’->0->’staff’->0->’title’ = ‘chief’
)
jsonb_pretty
-------------------------------------------
{ +
"department": [ +
{ +
“staff”: [ +
{ +
"name": “hoge", +
"title": “chief" +
} +
] +
} +
] +
}
3Copyright © 2015 NTT DATA Corporation
検索機能の向上
「name」がhoge、「title」がmanagerまたはchiefのデータを探そうとすると。。
SELECT
*
FROM
company as c
WHERE
EXISTS
(
SELECT
1
FROM
(
SELECT
jsonb_array_elements(t1.col1->’staff’) as col2
FROM
(
SELECT
jsonb_array_elements(jb->’department’) as col1
FROM
company
) as t1
) as t2
WHERE
t2.col2 ->> ‘name’ = ‘hoge’ AND
t2.col2 ->> ‘title’ IN (‘manager’, ‘chief’)
);
jsonb_pretty
-------------------------------------------
{ +
"department": [ +
{ +
“staff”: [ +
{ +
"name": “hoge", +
"title": “chief" +
} +
] +
} +
] +
}
3Copyright © 2015 NTT DATA Corporation
検索機能の向上
New Syntax :
{ ANY | EACH } { ELEMENT | KEY | VALUE | VALUE ANYWHERE } OF
container AS alias SATISFIES (expression)
SELECT
*
FROM
company
WHERE
ANY ELEMENT OF jb->’department’ AS d SATISFIES
(
ANY ELEMENT OF d->’staff’ AS s SATISFIES
(
s ->> ’name’ = ‘hoge’ AND
s ->> ‘title’ IN (‘manager’, ‘chief’)
)
);
3Copyright © 2015 NTT DATA Corporation
今後のはなし
JSONB型の圧縮
JSONB型はサイズが大きくなりがち。
データサイズについての改善も進められています!
- Rethinking JSONB -
by Alexander Korotkov, Konstantin Knizhnik, Oleg Bartunov
at PGCon 2015
3Copyright © 2015 NTT DATA Corporation
まとめ
 9.5でJSONB型データの操作がより便利に!
 9.6以降もさらなる進化に期待!
Copyright © 2011 NTT DATA Corporation
Copyright © 2015 NTT DATA Corporation