myna jpug study 20160220-postgresql-json-datatype
TRANSCRIPT
![Page 1: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/1.jpg)
MyNA JPUG 合同勉強会(2016-02-20)
PostgreSQL でJSON 型+ α の話
ぬこ@横浜 (@nuko_yokohama)
![Page 2: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/2.jpg)
2
自己紹介「 PostgreSQL ラーメン」
でググってください。
![Page 3: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/3.jpg)
3
自己紹介 ( こんなの作ってた )拡張名 説明ksj 漢数字で演算可能な誰得なデータ型ntext 日本語正規化比較や、 typo を含む類似検索を行う
誰得なデータ型と textsearch 用パッチneo4j_fdw グラフデータベース neo4j への誰得なコネクタhb_worker PostgreSQL 上で数当てゲームする誰得な
Back ground workerpg_sulog スーパーユーザの操作のみをロギングしたり、
ブロックしたりする、誰得な HOOK 拡張
PostgreSQL を無駄に使うのが趣味 (?) です。一部は https://github.com/nuko-yokohama に登録してあります。
![Page 4: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/4.jpg)
4
アジェンダPostgreSQL と非構造化データ
JSON と JSONBPostgreSQL 9.5 での改良
XML と hstoreJSON/JSONB の話がメインです
![Page 5: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/5.jpg)
5
PostgreSQL と非構造化データ
![Page 6: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/6.jpg)
6
構造化の観点から見た分類
あり
なし
完全
不完全
構造化データ構造化定義
半構造化データ
非構造化データ
構造が定義されている
構造の定義が不完全
構造が定義されている
構造の定義がない
![Page 7: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/7.jpg)
7
構造化の観点から見た分類種別 内容 例構造化データ 何らかの定義(スキーマ定義等)に
より、構造を事前に決定しておくデータ。
CREATE TABLE 文で定義されたテーブル
半構造化データ 事前の定義はあるが、定義内の一部の構造が存在しなくても良いデータ。
XML スキーマで定義された XML 文書
非構造化データ 事前の構造定義を持たないデータ。 任意の JSON 文書
通常、 RDBMS では上記の種別のデータのうち、構造化データを扱う。
![Page 8: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/8.jpg)
8
PostgreSQL と非構造データ型
PostgreSQL で通常扱うのは、「構造化データ」
PostgreSQL ではデータ型として「半構造化データ」「非構造化データ」(以降、両方とも「非構造化データ」と記述)を扱うしくみも用意されている。
![Page 9: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/9.jpg)
9
PostgreSQL と非構造データ型
PostgreSQL で使用可能な、非構造化データ型は以下の 4 種類
型名 対応バージョン 位置づけ 備考XML 8.2 ~ 本体機能 libxml2 依存hstore 8.3 ~ contribJSON 9.2 ~ 本体機能JSONB 9.4 ~ 本体機能
まずこっちの話からします
![Page 10: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/10.jpg)
10
JSON と JSONB
![Page 11: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/11.jpg)
11
JSON とは
JavaScript Object NotationXML よりも軽量
構造化されたデータを文字列で表現可能
![Page 12: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/12.jpg)
12
PostgreSQL におけるJSON への取り組み
9.2 から順調に進化。 9.5 でも…?
●JSON 型の導入。●2 つの JSON 型構築関数。●JSON 内の値を使った条件検索はできなかった。
●JSON 型関数・演算子の大幅な強化。
●JSON データ型へのパスによるアクセス。
●JSON 内の値を使った条件検索が可能に。
●JSONB 型の導入。●検索の高速化●独自演算子の追加●GIN インデックス対応
9.29.3
9.4
![Page 13: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/13.jpg)
13
JSON 型でできること
JSON 文字列のパースキーによる値の取り出しパスによる値の取り出し
PostgreSQL 配列や行との変換etc ・・・
![Page 14: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/14.jpg)
14
JSON 文字列のパース例正しい JSON 文字列
誤った JSON 文字列
※パースは JSON/JSONB 型に変換されるときに行われる。
jsonb=# SELECT '{"key1":"value1", "key2":[100, 20, 5]}'::json; json ---------------------------------------- {"key1":"value1", "key2":[100, 20, 5]}(1 row)
jsonb=# SELECT '{"key1":"value1", "key2":[100, 20, ]}'::json;ERROR: invalid input syntax for type json at character 8DETAIL: Expected JSON value, but found "]".CONTEXT: JSON data, line 1: {"key1":"value1", "key2":[100, 20, ]...STATEMENT: SELECT '{"key1":"value1", "key2":[100, 20, ]}'::json;ERROR: invalid input syntax for type jsonLINE 1: SELECT '{"key1":"value1", "key2":[100, 20, ]}'::json;
カンマの後に値がない…
![Page 15: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/15.jpg)
15
キーによる値の取り出しキーから JSON オブジェクトを取得
キーから文字列を取得
jsonb=# SELECT data->'Email' as email , data->'Full Name' as fullname FROM test ORDER BY id LIMIT 3; email | fullname ----------------------+------------------- "[email protected]" | "Carolyne Kohler" (null) | "Paul Weber DVM" "[email protected]" | "Florence Murphy"(3 rows)
jsonb=# SELECT data->>'Email' as email , data->>'Full Name' as fullname FROM test ORDER BY id LIMIT 3; email | fullname --------------------+----------------- [email protected] | Carolyne Kohler (null) | Paul Weber DVM [email protected] | Florence Murphy(3 rows)
![Page 16: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/16.jpg)
16
jsonb=# SELECT '{"person":{"name":{"first":"Tom","last":"Lane"},"age":59}}'::json #>> '{person, name, first}'; ?column? ---------- Tom(1 row)
パスによる値の取り出しperson, name, first のパスで取得
person
name
first last
age
Tom Lane
59
(root)
![Page 17: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/17.jpg)
17
jsonb=# SELECT '{"Name":{"First":"Oleg","Last":"Bartunov"},"Country":"Russia","Contributes":["hstore","JSON","JSONB","GIN"]}'::json #>> '{Contributes,2}'; ?column? ---------- JSONB(1 row)
パスによる値の取り出しContributes の 2番目 (0相対 ) を取得
Contributes
name
first last
Oleg
hstore
(root)
JSON JSONB GIN
[0] [1] [2] [3]
Bartunov
![Page 18: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/18.jpg)
18
式インデックスとの組合せ式インデックスの設定jsonb=# SELECT data FROM json_t LIMIT 1; { "Email": "[email protected]", "Created At": "1987-08-21T18:42:02.269Z", "Country": "Paraguay", "Id": 0, "Full Name": "Carolyne Kohler"}(1 row)
jsonb=# CREATE INDEX json_id_idx ON json_t USING btree ((data->>'Id'));CREATE INDEXjsonb=# \d json_t Unlogged table "public.json_t" Column | Type | Modifiers --------+---------+----------------------------------------------------- id | integer | not null default nextval('json_t_id_seq'::regclass) data | json | Indexes: "json_id_idx" btree ((data ->> 'Id'::text)) PostgreSQL は
「式」の結果に対してインデックスが設定できます!
![Page 19: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/19.jpg)
19
式インデックスとの組合せ式インデックスを利用した検索jsonb=# EXPLAIN ANALYZE SELECT data FROM json_t WHERE data->>'Id' = '1000'; Bitmap Heap Scan on json_t (cost=4.68..130.11 rows=50 width=32) (actual time=0.078..0.078 rows=1 loops=1) Recheck Cond: ((data ->> 'Id'::text) = '1000'::text) Heap Blocks: exact=1 -> Bitmap Index Scan on json_id_idx (cost=0.00..4.66 rows=50 width=0) (actual time=0.072..0.072 rows=1 loops=1) Index Cond: ((data ->> 'Id'::text) = '1000'::text) Planning time: 0.248 ms Execution time: 0.106 ms(7 rows)
![Page 20: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/20.jpg)
20
その他の JSON 関数
PostgreSQL 配列と JSON配列との変換行から JSON への変換
JSON から PostgreSQL 行への展開キー集合の取得
キーと値を与えて JSON を構築他にもいろいろ
あるよ!
![Page 21: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/21.jpg)
21
PostgreSQL 配列と JSON 配列との変換
jsonb=# SELECT array_to_json(ARRAY[1, 3.14, -1.2e3]); array_to_json ---------------- [1,3.14,-1200](1 row)
jsonb=# TABLE bar; id | n_datas | t_datas ----+------------------+------------------------ 1 | {1.32,9.76,5.55} | {bdho,fjoal} 2 | {6.43,0.48} | {vbwdahoi,3dsai,cfjia} 3 | {} | {}(3 rows)
jsonb=# SELECT array_to_json(bar.t_datas) FROM bar; array_to_json ------------------------------ ["bdho","fjoal"] ["vbwdahoi","3dsai","cfjia"] [](3 rows)
build_object_json()などと組み合わせて使うこともできる
![Page 22: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/22.jpg)
22
行から JSON への変換
jsonb=# TABLE foo; id | n_data | t_data ----+--------+---------- 1 | 8.93 | 366fd4cf 2 | 5.23 | 3f0a243b 3 | (null) | (null)(3 rows)
jsonb=# SELECT row_to_json(foo.*) FROM foo; row_to_json -------------------------------------------- {"id":1,"n_data":8.93,"t_data":"366fd4cf"} {"id":2,"n_data":5.23,"t_data":"3f0a243b"} {"id":3,"n_data":null,"t_data":null}(3 rows)
列名をキー名に、列値を値に変換する
列値が null の場合は、JSON の null に変換
![Page 23: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/23.jpg)
23
JSON から PostgreSQL 行への展開
jsonb=# select * from json_each_text('{"id": 2, "age": 59, "name": {"last": "Lane", "first": "Tom"}}'); key | value ------+---------------------------------- id | 2 age | 59 name | {"last": "Lane", "first": "Tom"}(3 rows)
※内側のキー ("first", "last") と値は展開しない。 ※ key, value という固定の列名として返却される。 ※ key も value も TEXT 型として返却される。
![Page 24: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/24.jpg)
24
キー集合の取得
jsonb=# TABLE test; {"id": 1, "name": {"first": "Oleg"}, "distribute": ["GIN", "hstore", "json", "jsonb"]} {"id": 2, "age": 59, "name": {"last": "Lane", "first": "Tom"}} {"id": 3, "name": {"nickname": "nuko"}, "distribute": ["ksj", "neo4jfdw"]}
jsonb=# SELECT DISTINCT jsonb_object_keys(data) FROM test; distribute age id name
以下のような JSONB を含む全レコードからキーを取得する。
jsonb_object_keys関数の結果
※内側のキー ("first", "last") は取得できない点に注意!※自分で Outer キーを指定して取得した JSONB に対して jsonb_object_keys を発行することは可能。
![Page 25: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/25.jpg)
25
キーと値を与えて JSON を構築
jsonb=# SELECT json_build_object('name',' ぬこ ','age', 17, 'hobby', ' ラーメン ');
{"name" : "ぬこ ", "age" : 17, "hobby" : "ラーメン "}
奇数番目の引数にキー名を、偶数番目の引数に値を与える。
jsonb=# SELECT jsonb_build_object( 'name',jsonb_build_object('first',' ぬこ ','last','横浜 '),
'age', 17, 'hobby', ' ラーメン ');
{"age": 17, "name": {"last": "横浜 ", "first": " ぬこ "}, "hobby": "ラーメン "}
jsonb_build_object()関数のネストも可能
データベース内の他の値からJSON/JSONB 型を構築する場合に
重宝する関数!
![Page 26: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/26.jpg)
26
JSON と JSONB
![Page 27: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/27.jpg)
27
JSON 型格納形式は文字列
JSONB 型格納形式は規定のバイナリ形式
データ型の導入専用演算子の追加
![Page 28: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/28.jpg)
28
JSON と JSONB の格納状態例
00001fb0 95 7b 22 61 61 61 22 20 3a 20 22 41 41 41 41 22 |.{"aaa" : "AAAA"|00001fc0 2c 20 22 62 62 62 31 22 20 3a 20 7b 22 63 63 63 |, "bbb1" : {"ccc|00001fd0 63 22 3a 20 22 43 43 43 43 31 22 7d 2c 20 22 62 |c": "CCCC1"}, "b|00001fe0 62 62 32 22 20 3a 7b 22 63 63 63 63 22 20 3a 20 |bb2" :{"cccc" : |00001ff0 22 43 43 43 43 32 22 7d 20 7d 00 00 00 00 00 00 |"CCCC2"} }......|
00001fa0 b5 03 00 00 20 03 00 00 80 04 00 00 00 04 00 00 |.... ...........|00001fb0 00 04 00 00 00 16 00 00 50 18 00 00 50 61 61 61 |........P...Paaa|00001fc0 62 62 62 31 62 62 62 32 41 41 41 41 00 01 00 00 |bbb1bbb2AAAA....|00001fd0 20 04 00 00 80 05 00 00 00 63 63 63 63 43 43 43 | ........ccccCCC|00001fe0 43 31 00 00 00 01 00 00 20 04 00 00 80 05 00 00 |C1...... .......|00001ff0 00 63 63 63 63 43 43 43 43 32 00 00 00 00 00 00 |.ccccCCCC2......|
{"aaa" : "AAAA", "bbb1" : {"cccc": "CCCC1"}, "bbb2" :{"cccc" : "CCCC2"} }
入力 JSON 文字列
JSON 型の格納状態
JSONB 型の格納状態
PostgreSQL 9.5.1で確認
入力文字そのまま
バイナリ化されたデータが格納される
![Page 29: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/29.jpg)
29
バイナリ形式で格納すると
何が嬉しいのか?
![Page 30: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/30.jpg)
30
JSONB は格納効率を優先はしていない格納サイズに関しては
むしろ JSON より大きくなるケースもある。
JSONB の格納性能もJSON と比較すると遅い。
![Page 31: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/31.jpg)
31
JSONB は検索効率を優先
JSON 関数を使ってキーによる検索を行ったときに
JSON と比較して非常に高速(性能検証結果は後述)
![Page 32: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/32.jpg)
32
JSONB データ型JSON 自体にはデータ型の概念がある。
PostgreSQL の JSONB 型もデータ型に一部対応している。
JSON 型 対応する PostgreSQL 型 備考
文字型 text エンコーディングの問題は注意。なお、キーは文字型扱い。
数値型 numeric 浮動小数点型の NaN や Infinity の表記は許容されない。
時刻型 (未対応) PostgreSQL では文字列扱い。
真偽値 boolean 小文字の true/false のみ許容。(on/off とかもダメ )
null - 小文字 null のみ許容。SQL NULL とは別概念。
![Page 33: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/33.jpg)
33
JSONB は入力したJSON 文字列は保持されない。
JSON は入力文字列をそのまま保持する。
![Page 34: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/34.jpg)
34
JSONB 入力結果が保持されない例(数値型)
jsonb=# INSERT INTO jsonb_t VALUES (1, '{"key":1, "value":100}'),(2, '{"key":2, "value":100.0}'),(3, '{"key":3, "value":1.00e2}'),(4, '{"key":4, "value":1.000e2}');INSERT 0 4jsonb=# SELECT * FROM jsonb_t ; id | data ----+---------------------------- 1 | {"key": 1, "value": 100} 2 | {"key": 2, "value": 100.0} 3 | {"key": 3, "value": 100} 4 | {"key": 4, "value": 100.0}(4 rows)
小数なしのnumeric として同値
小数点ありのnumeric として同値
格納後に取り出すと指数表記でなくなる
![Page 35: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/35.jpg)
35
JSON だと単に文字列として格納されているだけなので、入力形式そのままで出力される
jsonb=# INSERT INTO json_t VALUES jsonb-# (1, '{"key":1, "value":100}'),jsonb-# (2, '{"key":2, "value":100.0}'),jsonb-# (3, '{"key":3, "value":1.00e2}'),jsonb-# (4, '{"key":4, "value":1.000e2}')jsonb-# ;INSERT 0 4jsonb=# SELECT * FROM json_t; id | data ----+---------------------------- 1 | {"key":1, "value":100} 2 | {"key":2, "value":100.0} 3 | {"key":3, "value":1.00e2} 4 | {"key":4, "value":1.000e2}(4 rows)
![Page 36: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/36.jpg)
36
JSONB 入力結果が保持されない例(重複キー、キー名の順序)
jsonb=# SELECT '{"key_z":99, "key_q": 20, "key_q" :25, "key_a" : 3}'::json, '{"key_z":99, "key_q": 20, "key_q" :25, "key_a" : 3}'::jsonb;-[ RECORD 1 ]---------------------------------------------- json | {"key_z":99, "key_q": 20, "key_q" :25, "key_a" : 3} jsonb | {"key_a": 3, "key_q": 25, "key_z": 99}
jsonb=# SELECT '{"key_x":[ 1, 400, 8888, 2, 99, 25, 3]}'::json, '{"key_x":[ 1, 400, 8888, 2, 99, 25, 3]}'::jsonb ;-[ RECORD 1 ]---------------------------------- json | {"key_x":[ 1, 400, 8888, 2, 99, 25, 3]} jsonb | {"key_x": [1, 400, 8888, 2, 99, 25, 3]}
同一階層で重複したキーがある場合、後に記述したもののみ有効となる。また、キー名でソートされている。
配列の場合、順序は保証される。
最初の” key_q” は保持されない!
![Page 37: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/37.jpg)
37
JSONB 入力結果が保持されない例(空白の扱い)
jsonb=# SELECT '{"key_z" : 99, "key q": 20, "key_a" : "aa aa"}'::json, '{"key_z" : 99, "key q": 20, "key_a" : "aa aa"}'::jsonb; -[ RECORD 1 ]-------------------------------------------------- json | {"key_z" : 99, "key q": 20, "key_a" : "aa aa"} jsonb | {"key q": 20, "key_a": "aa aa", "key_z": 99}
キーまたは値でない JSON 文字列中の空白は、JSONB では無視される。また、 JSONB の検索結果として出力される JSON 文字列ではキーと値のセパレータである“ :” の後に 1つ空白文字を入れるという規則で文字列を生成している。
![Page 38: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/38.jpg)
38
JSONB 専用演算子 (9.4)演算子 意味
<@ 左辺の JSON が右辺のキー&値の組を含むかを評価する。
@> 右辺の JSON が左辺のキー&値の組を含むかを評価する。
? 左辺の JSON が右辺の(一つの)キーまたは要素を含むかどうかを評価する。
|? 左辺の JSON が右辺のキーまたは要素を 1つでも含むかどうかを評価する。( ANY 評価)
&? 左辺の JSON が右辺のキーまたは要素を全て含むかどうかを評価する。( ALL 評価)
![Page 39: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/39.jpg)
39
JSONB 専用演算子 (9.5追加 )演算子 意味
|| 指定したキーが存在しなければ、キー&値の組み合わせを追加し、存在すれば指定したキー&値の組み合わせを置換する。
- 指定したキーと合致するキー&値の組み合わせを削除する。。
- 指定した番号の配列要素を削除する。
#- 指定したパスに合致するキー&値の組み合わせ、または配列要素を削除する。
詳細は後で!
![Page 40: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/40.jpg)
40
@> 演算子と GIN
GIN インデックスとの組み合わせで、お手軽な
インデックスの作成が可能
![Page 41: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/41.jpg)
41
GIN インデックス
汎用転置インデックス配列型での利用
全文検索等でも利用※ これも JSONB と同じ開発チームで開発している。
http://www.sai.msu.su/~megera/wiki/Gin
![Page 42: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/42.jpg)
42
@>と GIN インデックス
jsonb=# SELECT data FROM jsonb_t LIMIT 1; {"Id": 0, "Email": "[email protected]", "Country": "Paraguay", "Full Name": "Carolyne Kohler", "Created At": "1987-08-21T18:42:02.269Z"}(1 row)
jsonb=# CREATE INDEX jsonb_idx ON jsonb_t USING gin (data jsonb_ops);CREATE INDEXjsonb=# \d jsonb_t Unlogged table "public.jsonb_t" Column | Type | Modifiers --------+---------+------------------------------------------------------ id | integer | not null default nextval('jsonb_t_id_seq'::regclass) data | jsonb | Indexes: "jsonb_idx" gin (data)
JSONB カラム自体に GIN インデックスを設定
JSONB 列自体にGIN インデックスを
設定する。
![Page 43: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/43.jpg)
43
この状態で @> 演算子(右辺にはキーと値の組み合わせ)を使うと GIN インデックスによる効率的な検索が可能になる
jsonb=# EXPLAIN SELECT data->'Full Name' as fullname, data->'Country' as country FROM jsonb_t WHERE data @> '{"Country" : "Monaco"}'; QUERY PLAN -------------------------------------------------------------------------- Bitmap Heap Scan on jsonb_t (cost=20.08..54.18 rows=10 width=160) Recheck Cond: (data @> '{"Country": "Monaco"}'::jsonb) -> Bitmap Index Scan on jsonb_idx (cost=0.00..20.07 rows=10 width=0) Index Cond: (data @> '{"Country": "Monaco"}'::jsonb) Planning time: 0.074 ms(5 rows)
@>と GIN インデックス
JSONB カラムに @> 演算子で条件を記述
@> + GIN の組み合わせはキーが不定でも有効!
![Page 44: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/44.jpg)
44
JSONB 型の実装
![Page 45: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/45.jpg)
45
JSON 型と JSONB 型の処理
JSON 型と JSONB 型のデータ格納データ取得
JSON関数処理の処理イメージを次ページ以降に示す。
![Page 46: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/46.jpg)
46
JSON 型の処理イメージJSON 文字列
JSONツリーJSON パーサ
JSON 型(文字列)
JSON 文字列
関数の結果
(そのまま出力)
格納時
取り出し時
JSON関数
JSON パーサ関数処理
JSONツリー
PostgreSQLストレージ
パーサではチェックのみを行う
処理時にもパースが必要
![Page 47: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/47.jpg)
47
JSONB 型の処理イメージJSON 文字列
JSONツリーJSON パーサ
JSONB 型(バイナリ)
JSON 文字列
関数の結果
文字列化
格納時
取り出し時
JSONB関数
関数処理
PostgreSQLストレージシリアライズ
処理する時にはバイナリを直接処理
パースとシリアライズを行う
![Page 48: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/48.jpg)
48
JSON ツリーparseState=0
pstate
res
res
type=jbvObject val.object.nPairs=3
keytype=jbvString
pair[0]
valtype=jbvString
len=3 val
AAA
len=2 val
aa
keytype=jbvString
valtype=jbvString
pair[1]
keytype=jbvString
pair[2]
len=2 val
bb
・・・
上記の JSON文字列をパースすると以下のようなツリー構造が生成される
※ PostgreSQL 9.4-beta2の場合
{"aa":"AAA","bb":"BBB","cc":"CCC"}
![Page 49: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/49.jpg)
49
格納サイズ
さっき説明した JSON と JSONB の処理内容から格納サイズを予想すると
以下のようになる。
格納サイズは JSONB よりもJSON のほうが小さい?
( JSONB はツリー構造情報も保持)
![Page 50: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/50.jpg)
50
以下のような JSON データ{ "Email": "[email protected]", "Created At": "1987-08-21T18:42:02.269Z", "Country": "Paraguay","Id":"0", "Full Name": "Carolyne Kohler"}
測定内容TEXT/JSON/JSONB カラムのみをもつテーブルを作成
上記 1万件を 10回 COPY した後のテーブルサイズを pg_relation_size() で測定
![Page 51: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/51.jpg)
51
格納サイズPostgreSQL 9.5.1で確認
text
json
jsonb
0 2 4 6 8 10 12 14 16 18 20
19.0
19.0
18.7
10万件データロード後のテーブルサイズ (MB)
9.4 では jsonb が少し大きかったが、
9.5 で少し改善された?
![Page 52: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/52.jpg)
52
性能比較
さっき説明した JSON と JSONB の処理内容から処理性能を予想すると
以下のようになる。
格納処理は JSON のほうが高速単なる SELECT は JSON のほうが高速?JSON 関数を使った場合は JSONB が高速
![Page 53: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/53.jpg)
53
測定環境
PC:Let's note SX4(SSD)OS:CentOS 7.0( メモリ 4GB)
PostgreSQL パラメータはデフォルト
![Page 54: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/54.jpg)
54
以下のような JSON データ{ "Email": "[email protected]", "Created At": "1987-08-21T18:42:02.269Z", "Country": "Paraguay", "Id": 0, "Full Name": "Carolyne Kohler"}
測定内容JSON/JSONB カラムをもつテーブルを UNLOGGED で作成
上記 1万件を 10回 COPYしたときの平均性能SELECT(10 万件 ) の平均性能
SELECT(10 万件 ) + JSON 演算子を使ったときの平均性能btree vs GIN インデックス検索性能
![Page 55: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/55.jpg)
55
TEXT
JSON
JSONB
0 5 10 15 20 25 30 35 40 45 50
14.65
17.49
43.71
1 万件ロード平均時間 (ms)
COPY 処理時間
TEXT と JSON の差分が 10000件分の JSON パース時間?JSON と JSONB の差分が 10000件文のシリアライズ時間?
PostgreSQL 9.5.1で測定
JSONB の挿入は結構遅い・・・
![Page 56: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/56.jpg)
56
JSON
JSONB
0 2 4 6 8 10 12 14 16 18 20
14.12
14.08
10 万件 COUNT(*)平均時間 (ms)
COUNT(*) 処理時間PostgreSQL 9.5.1で確認
10万件格納されたテーブルに対して、SELECT COUNT(*) FROM テーブル名 を実行
ほぼ同じですねー
![Page 57: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/57.jpg)
57
JSON
JSONB
0 20 40 60 80 100 120 140 160
136.55
25.42
10 万件 data->>'Country' 平均時間 (ms)
SELECT 処理時間
10万件格納されたテーブルに対して、SELECT data->'Country' FROM テーブル名 を実行
PostgreSQL 9.5.1で確認
JSON関数使用時はJSONB が圧倒的に早い!
![Page 58: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/58.jpg)
58
btree vs GINjsonb=# EXPLAIN ANALYZE SELECT * FROM test_jsonb WHERE data->>'Country' = 'Monaco'; Bitmap Heap Scan on test_jsonb (cost=12.29..1240.26 rows=500 width=161) (actual time=0.088..0.364 rows=310 loops=1) Recheck Cond: ((data ->> 'Country'::text) = 'Monaco'::text) Heap Blocks: exact=280 -> Bitmap Index Scan on jb_bi (cost=0.00..12.17 rows=500 width=0) (actual time=0.055..0.055 rows=310 loops=1) Index Cond: ((data ->> 'Country'::text) = 'Monaco'::text) Planning time: 0.052 ms Execution time: 0.402 ms
jsonb=# EXPLAIN ANALYZE SELECT * FROM test_jsonb WHERE data @> '{"Country":"Monaco"}'; Bitmap Heap Scan on test_jsonb (cost=28.77..362.50 rows=100 width=161) (actual time=0.650..1.004 rows=310 loops=1) Recheck Cond: (data @> '{"Country": "Monaco"}'::jsonb) Heap Blocks: exact=280 -> Bitmap Index Scan on jb_gi (cost=0.00..28.75 rows=100 width=0) (actual time=0.613..0.613 rows=310 loops=1) Index Cond: (data @> '{"Country": "Monaco"}'::jsonb) Planning time: 0.052 ms Execution time: 1.043 ms(7 rows)
GIN インデックス使用時
btree 式インデックス使用時
特定のキーを検索条件に使うと分かっている場合は
btree 式インデックスが有利!
![Page 59: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/59.jpg)
59
測定結果まとめ
格納: JSON が高速SELECT :ほぼ同じ?
JSON関数: JSONB が高速GIN より btree 式インデックスが高速
![Page 60: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/60.jpg)
60
格納効率優先なら JSON検索効率優先なら JSONB
入力形式を保持するなら JSON
⇒だいたいの場合、 JSONB で OK?
結局、 JSON と JSONB はどう使い分けるのか?
![Page 61: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/61.jpg)
61
PostgreSQL 9.5 での改良
![Page 62: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/62.jpg)
62
JSONB 専用演算子 (9.5追加 )演算子 意味
|| 指定したキーが存在しなければ、キー&値の組み合わせを追加し、存在すれば指定したキー&値の組み合わせを置換する。
- 指定したキーと合致するキー&値の組み合わせを削除する。。
- 指定した番号の配列要素を削除する。
#- 指定したパスに合致するキー&値の組み合わせ、または配列要素を削除する。
文書の部分更新が可能に!
![Page 63: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/63.jpg)
63
JSONB 型の改善9.4 まで(部分更新が出来ないので、更新結果の再構築 + 型変換が必要)
SELECT data FROM test WHERE (data->>'id')::int = 222; data ---------------------------------------------------------------- {"id": 222, "age": 18, "name": "nuko", "location": "Yokohama"}(1 row)
UPDATE test SET data = json_build_object( 'id', data->>'id', 'name', data->>'name', 'location', data->>'location', 'age', 20)::jsonb WHERE (data->>'id')::int = 222;UPDATE 1SELECT data FROM test WHERE (data->>'id')::int = 222; data ------------------------------------------------------------------ {"id": "222", "age": 20, "name": "nuko", "location": "Yokohama"}(1 row)
書くのも面倒。性能もよろしくない。
キーが不定の場合対応できない?
![Page 64: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/64.jpg)
64
JSONB 型の改善9.5 から(部分更新演算子でシンプルに記述可能)
SELECT data FROM test WHERE (data->>'id')::int = 222; data ---------------------------------------------------------------- {"id": 222, "age": 18, "name": "nuko", "location": "Yokohama"}(1 row)
UPDATE test SET data = data || '{"age":20}' WHERE (data->>'id')::int = 222;UPDATE 1SELECT data FROM test WHERE (data->>'id')::int = 222; data ---------------------------------------------------------------- {"id": 222, "age": 20, "name": "nuko", "location": "Yokohama"}(1 row)
部分更新演算子でスッキリ!性能上も有利!
![Page 65: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/65.jpg)
65
JSON 型の改善部分更新演算子による性能改善効果
比較用 UPDATE jsonb_build_object 9.5 演算子0
1000
2000
3000
4000
5000
6000
7000
8000
9000
10000
3743
8574
5362
JSONB 100 万件更新時間
更新時間
(ms)
こうかはばつぐんだ!
![Page 66: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/66.jpg)
66
JSON 型の想定用途
![Page 67: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/67.jpg)
67
多様なログの収集(スキーマが規定できないケース)
JSON化
ログ
ログ
ログ
JSONBカラムに格納GIN/btreeインデックス設定
ログ検索アプリケーション
rsyslog等ログ
既存の表JSONB表
![Page 68: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/68.jpg)
68
微妙なテーブル設計の救済?CREATE TABLE foo { id integer primary key, name text,・・・ memo1 text, memo2 text, memo3 text,・・・ memo100 text}
CREATE TABLE foo { id integer primary key, name text,・・・ memo jsonb}
※きちんと設計をしていれば不要だろうけど・・・
とりあえず予備カラム群
作っちゃう奴~
JSON 型にまとめてしまおう
![Page 69: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/69.jpg)
69
MongoDB 等のドキュメント指向 DB の代替?
or
本当にいいのかな・・
![Page 70: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/70.jpg)
70
当たり前の話ですが、JSON/JSONB を
過剰に使うのも考えもの。きちんと DB を設計した上で
うまくハマるところで使うべき。 ,j;;;;;j,. --- 一、 ` ― --‐ 、 _ l;;;;;; { ;;;;;; ゝ T 辷 i フ i f' 辷 j ァ !i;;;;; なんでも JSON に入れればいい・・・ ヾ ;;; ハ ノ .::!l リ ;;r ゙ `Z;i 〈 .,_..,. ノ ;;;;;;;;> そんなふうに考えていた時期が ,; ぇハ、 、 _,. ー - 、 _',. , f゙ : Y;;f. 俺にもありました ~'' 戈ヽ `二 ´ r'´:::. `!
![Page 71: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/71.jpg)
71
PostgreSQL の他の非構造データ型
せっかくなのでXML 型と hstore 型についても、
ちょっと話します
![Page 72: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/72.jpg)
72
XML 型
XML を格納するデータ型本体機能 (configure で指定 )格納時に XML パースを行なう型自体に比較演算機能はないxpath によるアクセスが可能SQL 関数による XML 型構築libxml2 ライブラリに依存
「 XML滅べ」って言ってもなかなか滅びない・・・
![Page 73: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/73.jpg)
73
XML 型の処理イメージXML 文字列
XML パーサ
XML 型(文字列)
XML 文字列
関数の結果
(そのまま出力)
格納時
取り出し時
xpath関数
XML パーサ関数処理
xpath処理
PostgreSQLストレージ
パーサではチェックのみを行う
![Page 74: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/74.jpg)
74
XML 型でできること
XML 文字列のパースと格納xpath による結果の取り出し
SQL 関数による XML 型の構築
![Page 75: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/75.jpg)
75
XML 型の使用例XML 型カラムを持つテーブルother=# \d xml_t Table "public.xml_t" Column | Type | Modifiers --------+---------+---------------------------------------------------- id | integer | not null default nextval('xml_t_id_seq'::regclass) data | xml |
other=# SELECT data FROM xml_t; <rdb_t><email>[email protected]</email><created_at>1987-08-21T18:42:02.269Z</created_at><country>Paraguay</country><id>0</id><full_name>Carolyne Kohler</full_name></rdb_t> <rdb_t><email>[email protected]</email><created_at>1989-03-16T14:37:36.825Z</created_at><country>France</country><id>1</id><full_name>Paul Weber DVM</full_name></rdb_t> <rdb_t><email>[email protected]</email><created_at>1980-02-19T04:16:52.113Z</created_at><country>Uzbekistan</country><id>2</id><full_name>Florence Murphy</full_name></rdb_t>(3 rows)
![Page 76: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/76.jpg)
76
XML 型の使用例xpath 関数による XML 文書からの抽出
(例) xpath関数は XML配列を返却するので、テキストを取り出す場合に、 TEXT
配列にキャストして最初の要素を取り出すなどの操作が必要。(例)名前空間 url と prefix の組を配列化して xpath関数に渡す必要がある。
other=# SELECT (xpath('/rdb_t/email/text()', data)::text[])[1] as email,(xpath('/rdb_t/full_name/text()', data)::text[])[1] as fullnameFROM xml_t; email | fullname --------------------------+----------------- [email protected] | Carolyne Kohler [email protected] | Paul Weber DVM [email protected] | Florence Murphy(3 rows)
XML 型を使うのはちょい面倒・・・
![Page 77: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/77.jpg)
77
hstore 型
Key-Value store データ型contrib モジュールネストはできない。
部分更新インタフェースあり※作者は JSONB と同じ Oleg 氏
シンプルなKey-Value 型
![Page 78: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/78.jpg)
78
hstore 型の処理イメージhstore 文字列
hstore パーサ
hstore 型(バイナリ)
hstore 文字列
関数の結果
文字列化
格納時
取り出し時
hstore関数
関数処理
PostgreSQLストレージシリアライズ
パースとバイナリ化を行う
処理する時にはバイナリを直接処理
パースとバイナリ化を行う
![Page 79: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/79.jpg)
79
hstore 型でできること
hstore 文字列のパースと格納キーによる値の取り出し
キーと値のセットで追加 / 更新指定キーのキー&値を削除レコードからの生成
JSON への変換GIN インデックス対応
![Page 80: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/80.jpg)
80
hstore 型の使用例hstore 型カラムを持つテーブルother=# \dx List of installed extensions Name | Version | Schema | Description ---------+---------+------------+-------------------------------------------------- hstore | 1.3 | public | data type for storing sets of (key, value) pairs plpgsql | 1.0 | pg_catalog | PL/pgSQL procedural language(2 rows)
other=# \d hstore_t Table "public.hstore_t" Column | Type | Modifiers --------+---------+------------------------------------------------------- id | integer | not null default nextval('hstore_t_id_seq'::regclass) data | hstore |
CREATE EXTENSION で登録が必要です。
![Page 81: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/81.jpg)
81
hstore 型の使用例hstore 型カラムの検索other=# SELECT data FROM hstore_t; "id"=>"0", "email"=>"[email protected]", "country"=>"Paraguay", "full_name"=>"Carolyne Kohler", "created_at"=>"1987-08-21T18:42:02.269Z" "id"=>"1", "email"=>"[email protected]", "country"=>"France", "full_name"=>"Paul Weber DVM", "created_at"=>"1989-03-16T14:37:36.825Z" "id"=>"2", "email"=>"[email protected]", "country"=>"Uzbekistan", "full_name"=>"Florence Murphy", "created_at"=>"1980-02-19T04:16:52.113Z"(3 rows)
“キー名” =>” 値”の形式で出力される。
![Page 82: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/82.jpg)
82
hstore 型の使用例hstore 型カラムから特定のキーのみ抽出
条件式を使う例
other=# SELECT data->'email' as email, data->'full_name' as full_name FROM hstore_t; email | full_name --------------------------+----------------- [email protected] | Carolyne Kohler [email protected] | Paul Weber DVM [email protected] | Florence Murphy(3 rows)
other=# SELECT data->'id' as id, data->'email' as email FROM hstore_t WHERE data->'id' = '1'; id | email ----+-------------------------- 1 | [email protected](1 row)
XML 型 /xpath 関数を使うよりシンプル!
“->” という演算子にキー名を与えて取り出す
![Page 83: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/83.jpg)
83
XML, hstore, JSON/JSONB 比較データ型 表現能力 格納サイズ 参照性能 更新性能XML ◎ △ △ △
hstore △ ○ ◎ ◎
JSON ○ ○ ○ ◎
JSONB ○ ○ ◎ ○
XML は表現能力は高いが扱いにくいhstore はシンプルだが速いJSONB は良いとこ取り?⇒ 用途で使い分け可能
![Page 84: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/84.jpg)
84
まとめ
![Page 85: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/85.jpg)
85
PostgreSQL は非構造化データを扱う手段がいくつかある
XML/hstore/JSON/JSONB のどれを使うかは要件次第
非構造化データ型を本当に使うべきかどうかもきちんと検討しよう
![Page 86: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/86.jpg)
86
ご清聴ありがとうございました
![Page 87: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/87.jpg)
87
Question?
![Page 88: MyNA JPUG study 20160220-postgresql-json-datatype](https://reader031.vdocuments.site/reader031/viewer/2022021506/586e8d211a28aba0038b8777/html5/thumbnails/88.jpg)
88
参考情報●本家文書:“ PostgreSQL 9.5 Documentation”
http://www.postgresql.org/docs/9.5/static/index.html●本家Wiki :“ What's new in PostgreSQL 9.5”
https://wiki.postgresql.org/wiki/What%27s_new_in_PostgreSQL_9.5●日本ヒューレット・パッカード株式会社 篠田さん●「篠田の虎の巻」“ PostgreSQL 9.5 新機能検証結果”
http://community.hpe.com/t5/日本のお客様向け-エンタープライズ-トピックス/篠田の虎の巻その4を公開-大幅に機能強化されたPostgreSQL-9-5の世界へ飛び込もう/ba-p/6797055?profile.language=ja#.VchDOE0w-Sw
●
●SRA OSS, Inc. 高塚さん~徹底検証報告~ 次期メジャーバージョン PostgreSQL 9.5 の実力 http://www.sraoss.co.jp/event_seminar/2015/PostgreSQL9.5-report.pdf
●NTTDATA 澤田さん PostgreSQL 9.5 新機能紹介http://www.slideshare.net/hadoopxnttdata/postgresql-95-new-features-nttdata
●Michael Paquier さんの blog● http://michael.otacoo.com/●”7 つのデータベース 7 つの世界”ISBN 978-274-06907-6
●・・・ And Many Postgres Users
むしろ、これらが必見ですよ!