FORCIAã¢ããã³ãã«ã¬ã³ããŒ2020 8æ¥ç®ã®èšäºã§ãã ãã©ã«ã·ã¢ã§æ
è¡æšªææ€çŽ¢ãäž»ã«ãšã³ãžãã¢ãªã³ã°ãããŠããŸããçžæŸ€ãšãããŸãã æ®æ®µã¯äž»ã«PostgreSQLã䜿ã£ãŠããŒã¿åŠçã®é«éåãšããã«åå¯ãã«èŠæŠããæ¥ã
ãéã£ãŠããŸãã å°ãåã« PostgreSQL12 ãç»å ŽããŸãããïŒ ãã©ã«ã·ã¢ã§åãç§ãšããŠã¯æ€çŽ¢ãåçš®ã€ã³ããã¯ã¹ã®æ§èœæ¹åãã©ã®çšåºŠã®ç©ãªã®ããäžçªæ°ã«ãªããšãããªã®ã§ãããåãã㊠JSON Pathã«å¯Ÿå¿ ãšããã®ãæ°ã«ãªããŸããã å®ã¯ããŸãŸã§jsonïŒjsonbïŒåããŒã¿ãããŸãæ±ã£ãããšããªãã£ãã®ã§ïŒPostgreSQLã«ä»èšèªã®ããŒã¿åãæã¡èŸŒãçç±ãåããããç©æ¥µçã«ç¥ãã«ããæ©äŒããªãã£ãã®ã§ïŒããããæ©ã«å匷ããããšæããŸãã jsonbã1ããåŠã³å§ããåãã¹ã¿ãŒãå°ç¹ã«ç«ã€ãŸã§ã®èª¿æ»ã»ç¢ºèªãšããããšã§ãã0ãŸã§ã®jsonbããšããã¿ã€ãã«ã§ãéãããŸãïŒ åºæ¬ç¥èç·š(jsonbãšã¯) https://www.postgresql.jp/node/320 ããããJSONãšããã®ã¯JavaScript ã®ããŒã¿ãã©ãŒãããã§ãã PostgreSQLã§ã9.2ç³»ããjsonåããµããŒããããŠããŸããJavaScriptã®JSONãšéãç¹ã¯ããµãŒã笊å·åæ¹åŒãUTF-8ã§ãªããã°ãªããªãç¹ãšãªã£ãŠããŸãïŒå
¬åŒããã¥ã¡ã³ãã«ã¯ å³å¯ã«ä»æ§ãæºããJSONã«å¯Ÿå¿ããããšãã§ããŸãã ãšèšèŒãããŠããŸãããå³å¯ã§ãªãããŒã¿åœ¢åŒã«äœã®æå³ããããŸããããïŒãtextåã«jsonã§æåãæžãã®ãšéããjsonåã«ãªã£ãŠããç¹ã§åªã£ãŠããŸãããããã€ãã®é¢æ°ã䜿çšã§ããŸãã ⻠以åŸãåºå¥ã®ããPostgreSQLã®jsonã®ããšã®ã¿ãå°æåã§jsonãšèšèŒããŸãã äœè«ã§ã¯ããããŸããåŒç€Ÿã¯ãã€ãŠPostgreSQLã«jsonãå®è£
ãããåã«ãjsonåãç¬èªå®çŸ©ãæäœã®ããã®é¢æ°ã©ã€ãã©ãªãäœæããŠããŸããã JSONã¯ã·ã³ãã«ã§å¯èªæ§ãé«ããäœããšäŸ¿å©ãªã®ã§ãwebã¢ããªãäœæããäžã§ãããšäŸ¿å©ãªã±ãŒã¹ãå€ã
ãããŸãã å
¬åŒæç« ã«ããã°ãPostgreSQL9.4ããã¯jsonbãšãã圢åŒãçŸããŸãããããã¯jsonåãšã¯ä»¥äžã®ç¹ã§ç°ãªãããã§ãã jsonããŒã¿åã¯å
¥åããã¹ãã®æ£ç¢ºãªã³ããŒã§æ ŒçŽããåŠç颿°ãå®è¡ãããã³ã«åè§£æããå¿
èŠããããŸãã jsonbããŒã¿åã§ã¯ãåè§£ããããã€ããªåœ¢åŒã§æ ŒçŽãããŸãã æ ŒçŽãããšãã«ã¯å€æã®ãªãŒããŒãããã®ããå°ãé
ããªããŸãããåŠçãããšãã«ã¯ãå
šãåè§£æãå¿
èŠãšãããªãã®ã§å€§å¹
ã«é«éåãããŸãã ãŸã jsonbåã®éèŠãªå©ç¹ã¯ã€ã³ããã¯ã¹ããµããŒãããŠããããšã§ãã jsonåã¯å
¥åå€ã®ã³ããŒãæ ŒçŽããŠããã®ã§ãæå³çã«éèŠã§ãªãããŒã¯ã³éã®ç©ºçœã ãã§ãªããJSONãªããžã§ã¯ãå
ã®ããŒã®é åºãç¶æããŸãã ãŸããJSONãªããžã§ã¯ãå
ã«åãããŒãšå€ãè€æ°å«ãŸããŠããŠããã¹ãŠã®ããŒïŒå€ã®ãã¢ãä¿æãããŸãã(ãã®åŠç颿°ã¯æåŸã®å€ïŒã€ãåŠçãããããããã°æžã¿ãŸãã) ãããšã¯å¯Ÿç
§çã«ãjsonbã¯ç©ºçœãä¿æããŸããããªããžã§ã¯ãããŒã®é åºãä¿æãããéè€ãããªããžã§ã¯ãããŒãä¿æããŸãããéè€ããŒãå
¥åã§æå®ãããå Žåã¯ãæåŸã®å€ãä¿æãããŸãã PostgreSQL 12.4ææž ããåŒçš JSONãšéãã空çœãškeyã®éè€ãèš±ãããŠããªãããã§ãããšã¯ããããŸãšãã«JSONãéçšããå Žåãvalueãkeyããªãã£ãã空çœã ã£ããæºããããããšãã°ã®åå ã«ãªããããã§ãããkeyã®éè€ããã£ãŠã®ã»ãã§ãã®ã§ãã»ãšãã©ã®ã¢ããªã±ãŒã·ã§ã³ã§ã¯jsonbã§ãŸã£ããåé¡ããªãã®ã§ã¯ãªãã§ããããã ãããŠjsonbã§äŸ¿å©ãªç¹ã¯valueã®ã¿ã®å
šææ€çŽ¢ãã§ããç¹ããããŠé«éãªæ€çŽ¢ãå®è£
ããã«ããã£ãŠéèŠãªããšã§ããã€ã³ããã¯ã¹ã匵ãããšããç¹ã§ããjsonbã¯GINã€ã³ããã¯ã¹ã䜿çšããŠãkeyãšvalueã®ãã¢ã®æ€çŽ¢ãš @> æŒç®åïŒå·Šã®JSONå€ã¯ãããã¬ãã«ã«ãããŠå³ã®JSONãã¹ãŸãã¯å€ãå
å«ãããïŒããµããŒãããã€ã³ããã¯ã¹ãäœæããããšãã§ããŸãã ãããŠPostgreSQL12ããã¯jsonpathåãšãããã®ãå®è£
ãããŸãããããã«ãã£ãŠãjsonbã®ç¹å®ã®pathã«ã¢ã¯ã»ã¹ãããããªããç¹å®ã®èŠçŽ ãååšãããã©ãããäžå®ä»¥äžã®å€ãã©ããããã£ã«ã¿ãŒã§ããããã«ãªããŸãããjsonpathã®æ³šæç¹ãšããŠã¯ã倧æåå°æåã®åºå¥ãããããšãšãé
åã€ã³ããã¯ã¹ã1ããå§ãŸãç¹ã§ããã®ãããã¯JavaScriptã«æµžé£ãããŠã¡ãã£ãšå«ãªæãã§ããã ãããŸã§å
å®ããŠããã®ã§ããã°ãããšã¯äœ¿ã£ãŠã¿ãŠçè§£ããã°åŒ·ãéžæè¢ã«ãªãããã§ãïŒ åºæ¬å®è·µç·š ããŠãç°¡åã«ã§ã¯ãããŸããããããã®æ©èœã䜿ã£ãŠã¿ãããšæããŸãã DBäœæ ãŸãUTF-8ã§DBãäœæããŸãã createdb -E utf-8 jsontest æååããã®jsonåãjsonbåãã£ã¹ã jsonãjsonbã¯textãããã£ã¹ãããããšãåºæ¥ãŸãã # textããã£ã¹ãã§ãã select '{"index":1,"value":"a"}'::json, '{"index":1,"value":"a"}'::jsonb; json | jsonb -------------------------+---------------------------- {"index":1,"value":"a"} | {"index": 1, "value": "a"} # textãjson圢åŒã§ãªããšãã¯ä»¥äžã®ãããªãšã©ãŒã«ãªã select '{"index":1:"value":"a"}'::json; ERROR: invalid input syntax for type json LINE 1: select '{"index":1:"value":"a"}'::json; ^ DETAIL: Expected "," or "}", but found ":". CONTEXT: JSON data, line 1: {"index":1:... å€éšãã¡ã€ã«ã®äœ¿çš å€éšãã¡ã€ã«ãCOPYããŠjsonåjsonbåããŒã¿ãäœæããããšãã§ããŸãã COPYã®éã«ã¯ããã«ã¯ãªãŒããŒã·ã§ã³ãšã«ã³ããã«ã©ã äžã«å¿
é ã«ãªãããšãããCSVã¢ãŒãã«ããtsvã§åã蟌ãã®ãããããã§ãã å€éšãã¡ã€ã«ïŒã¿ãåºåãtsvïŒ 1 {"idx" : 1, "value" : "a a"} 2 {"idx" : 2, "value" : "b a"} # å€éšãã¡ã€ã«ã䜿çšã§ããã drop table if exists testjson; create table testjson ( idx int ,json_column json ); copy testjson from '/path/to/json.tsv' delimiter E'\t'; drop table if exists testjsonb; create table testjsonb ( idx int ,jsonb_column jsonb ); copy testjsonb from '/path/to/json.tsv' delimiter E'\t'; ãŸãã¯jsonå, jsonbåã®ã«ã©ã ãæã€ããŒãã«ãäœæããŠã¿ãŸãã -- å
ããŒãã«ã®äœæ DROP TABLE IF EXISTS testtext; CREATE TABLE testtext AS ( SELECT idx, concat('{"idx":',idx::text,',"value1":"', substring(md5(idx::text),1,2), '","value2":"', md5(idx::text),'"}') AS text_column FROM ( SELECT generate_series(1,1000000) AS idx )s ); ANALYZE testtext; -- jsonããŒãã«ã®äœæ DROP TABLE IF EXISTS testjson; CREATE TABLE testjson AS ( SELECT idx ,text_column::json AS json_colmun FROM testtext ); ANALYZE testjson; -- jsonbããŒãã«ã®äœæ DROP TABLE IF EXISTS testjsonb; CREATE TABLE testjsonb AS ( SELECT idx ,text_column::jsonb AS jsonb_colmun FROM testtext ); ANALYZE testjsonb; ããŒã¿ãµã€ãºã¯jsonbåã倧ãããªã£ãŠããããšãããããŸãã SELECT relname ,(relpages / 128) AS mbytes FROM pg_class WHERE relname like 'test%' ORDER BY relname; relname | mbytes -----------+-------- testjson | 104 testjsonb | 120 testtext | 104 (3 rows) ç°¡åãªæäœã®ç¢ºèª ç¹å®ã®ãã¹ã®å€ãåãåºã -> int ã§jsoné
åèŠçŽ ã -> text ã§jsonãªããžã§ã¯ããã£ãŒã«ãã®åãåºãã #> path ã§ãã¹ã«ããJSONãªããžã§ã¯ããååŸããããã®å Žåã > ã >> ãšæžããšãªããžã§ã¯ãã§ã¯ãªãtextã«ãã£ã¹ããããŸãã select '[{"a":"foo"},{"b":"bar"},{"c":"baz"}]'::json->2; ?column? ------------- {"c":"baz"} (1 row) select '{"a": {"b":"foo"}}'::json->'a'; ?column? ------------- {"b":"foo"} (1 row) select '{"a": {"b":{"c": "foo"}}}'::json#>'{a,b}'; ?column? -------------- {"c": "foo"} (1 row) # -> ã¯jsonbã®ãŸãŸãªã®ã§åããæãã§ããŸã select '[{"a":"foo"},{"b":"bar"},{"c":"baz"}]'::json->2->'c'; ?column? ---------- "baz" (1 row) # ååšããªãpathã¯ç©ºã«ãªã£ãŠããŸãïŒãšã©ãŒã«ã¯ãªããŸããïŒ select '{"a":{"b":{"c":"d"}}}'::jsonb->'a'->'c'; ?column? ---------- (1 row) ãã¹ã®è¿œå ãšåé€ è¿œå 㯠|| ã§ åé€ã¯ - ã§ãã(ã·ã³ãã«ã§ããïŒ) select '{"a":"b"}'::jsonb || '{"c":"d"}'::jsonb; ?column? ---------------------- {"a": "b", "c": "d"} (1 row) select '{"a":"b","c":"d"}'::jsonb - 'a'; ?column? ------------ {"c": "d"} (1 row) ãªãã远å ã®éã«åãkeyããšãããšãã§ããªãã®ã§å³èŸºãåªå
ãããããã§ãã selectã'{"a":"b"}'::jsonb || '{"a":"c"}'::jsonb; ?column? ------------ {"a": "c"} (1 row) ãããã¬ãã«ããŒã®ååšãã§ã㯠? text textãšãããããã¬ãã«ããŒãååšãããã©ããã select '{"a":"b","c":"d"}'::jsonb?'a'; ?column? ---------- t (1 row) select '{"a":"b","c":"d"}'::jsonb?'b'; ?column? ---------- f (1 row) select '{"a":"b","c":"d"}'::jsonb?'c'; ?column? ---------- t (1 row) ?| array text é
åäžã®textã®ãããã¬ãã«ããŒãäžã€ã§ãååšãããã©ããã select '{"a":"b","c":"d"}'::jsonb?|array['b','c']; ?column? ---------- t (1 row) ?& array text é
åäžã®textã®ãããã¬ãã«ããŒããã¹ãŠååšãããã©ããã select '{"a":"b","c":"d"}'::jsonb?&array['b','c']; ?column? ---------- f (1 row) select '{"a":"b","c":"d"}'::jsonb?&array['a','c']; ?column? ---------- t (1 row) pathãšvalueã®çµã¿åãããåãåããã åè¿°ã®æŒç®å -> ããã㯠#> ãš ïŒ ãçµã¿åãããŸãã select '{"a":{"b":{"c":"d"}}}'::jsonb#>'{"a","b","c"}' ? 'd'; ?column? ---------- t (1 row) ãããã¬ãã«ã«ãããŠå³èŸºã®jsonbãå«ããã©ãã @> ã䜿çšããŸãã select '{"a":{"b":{"c":"d"}}}'::jsonb @> '{"c":"d"}'::jsonb; ?column? ---------- f (1 row) select '{"a":{"b":{"c":"d"}}}'::jsonb->'a'->'b' @> '{"c":"d"}'::jsonb; ?column? ---------- t (1 row) ã€ã³ããã¯ã¹ä»äžïŒé«éåïŒ å
¬åŒããã¥ã¡ã³ãã«ãããšããããã¬ãã«ããŒã®ååšãã§ãã¯ããkeyãšvalueã®çµã¿åããããå³èŸºã®jsonbãå«ããã©ãããã§indexãæå¹ã«æŽ»çšã§ããããã§ãããããã確èªããŠã¿ãŸãããã ãããã¬ãã«ããŒã®ååšãã§ãã¯(ãã¹ãŠã®å Žåãããããå Žåãšäžéšã®ã¿ãããããå Žå) indexãªãã§æ€çŽ¢ãè¡ãå Žåã EXPLAIN ANALYZE SELECT * FROM testjsonb WHERE (jsonb_colmun) ? 'value1' ; QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------- Gather (cost=1000.00..21693.33 rows=1000 width=92) (actual time=0.121..235.050 rows=1000000 loops=1) Workers Planned: 2 Workers Launched: 2 -> Parallel Seq Scan on testjsonb (cost=0.00..20593.33 rows=417 width=92) (actual time=0.015..121.201 rows=333333 loops=3) Filter: (jsonb_colmun ? 'value1'::text) Planning Time: 0.068 ms Execution Time: 289.437 ms (7 rows) UPDATE testjsonb SET jsonb_colmun = jsonb_colmun || '{"value3":"1"}'::jsonb WHERE (jsonb_colmun->'idx')::int4 % 100 = 0; -- 1%ã®ã«ã©ã ã«ããŒãè¶³ã ANALYZE testjsonb; EXPLAIN ANALYZE SELECT * FROM testjsonb WHERE (jsonb_colmun) ? 'value3' ; QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------- Gather (cost=1000.00..21866.33 rows=1000 width=93) (actual time=36.314..123.155 rows=10000 loops=1) Workers Planned: 2 Workers Launched: 2 -> Parallel Seq Scan on testjsonb (cost=0.00..20766.33 rows=417 width=93) (actual time=33.251..118.628 rows=3333 loops=3) Filter: (jsonb_colmun ? 'value3'::text) Rows Removed by Filter: 330000 Planning Time: 0.074 ms Execution Time: 123.707 ms (8 rows) åçŽã«jsonbã«ã©ã ã«GINã匵ã£ãå Žåã¯ããããã¬ãã«ããŒã®ååšãã§ãã¯ãé«éåããŸãã ããããªããå¿
ãindexã䜿çšãããŠããŸãããã¹ãŠã®ã¬ã³ãŒããæã£ãŠããvalue1ãšããã«ã©ã ã«å¯ŸããŠååšãã§ãã¯ãè¡ã£ãŠãindexã䜿çšãããŸãã 以äžã®2ã€ã®çç±ã§æ€çŽ¢ãé
ããªãããã§ãã indexã䜿çšããŠããåIOãçºçããŠãããã workerãåå²ããªããã DROP INDEX IF EXISTS idxgin; CREATE INDEX idxgin ON testjsonb USING GIN (jsonb_colmun); ANALYZE testjsonb; EXPLAIN ANALYZE SELECT * FROM testjsonb WHERE (jsonb_colmun) ? 'value1' ; QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------- Bitmap Heap Scan on testjsonb (cost=27.75..3186.69 rows=1000 width=92) (actual time=79.083..441.709 rows=1000000 loops=1) Recheck Cond: (jsonb_colmun ? 'value1'::text) Heap Blocks: exact=15385 -> Bitmap Index Scan on idxgin (cost=0.00..27.50 rows=1000 width=0) (actual time=75.965..75.966 rows=1000000 loops=1) Index Cond: (jsonb_colmun ? 'value1'::text) Planning Time: 0.117 ms Execution Time: 493.719 msã<-- é
ããªã£ãŠããŸã (7 rows) ANALYZE testjsonb; EXPLAIN ANALYZE SELECT * FROM testjsonb WHERE (jsonb_colmun) ? 'value3' ; QUERY PLAN ----------------------------------------------------------------------------------------------------------------------- Bitmap Heap Scan on testjsonb (cost=27.75..3190.76 rows=1000 width=93) (actual time=0.764..4.349 rows=10000 loops=1) Recheck Cond: (jsonb_colmun ? 'value3'::text) Heap Blocks: exact=174 -> Bitmap Index Scan on idxgin (cost=0.00..27.50 rows=1000 width=0) (actual time=0.733..0.733 rows=10000 loops=1) Index Cond: (jsonb_colmun ? 'value3'::text) Planning Time: 0.138 ms Execution Time: 4.883 ms (7 rows) keyãšvalueã®çµã¿åãã indexãªãã§æ€çŽ¢ãè¡ãå Žåã EXPLAIN ANALYZE SELECT * FROM testjsonb WHERE (jsonb_colmun->'value1') ? '00'; QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------ Gather (cost=1000.00..22735.00 rows=1000 width=92) (actual time=0.432..210.369 rows=3878 loops=1) Workers Planned: 2 Workers Launched: 2 -> Parallel Seq Scan on testjsonb (cost=0.00..21635.00 rows=417 width=92) (actual time=0.371..205.503 rows=1293 loops=3) Filter: ((jsonb_colmun -> 'value1'::text) ? '00'::text) Rows Removed by Filter: 332041 Planning Time: 0.068 ms Execution Time: 210.628 ms (8 rows) GINã以äžã®ããã«äœ¿çšããããšã§keyãšvalueã®çµã¿åãããé«éåããŸãã DROP INDEX IF EXISTS idxgintag; CREATE INDEX idxgintag ON testjsonb USING GIN ((jsonb_colmun->'value1')); ANALYZE testjsonb; EXPLAIN ANALYZE SELECT * FROM testjsonb WHERE (jsonb_colmun->'value1') ? '00'; QUERY PLAN ------------------------------------------------------------------------------------------------------------------------- Bitmap Heap Scan on testjsonb (cost=19.75..3181.19 rows=1000 width=92) (actual time=2.741..23.530 rows=3878 loops=1) Recheck Cond: ((jsonb_colmun -> 'value1'::text) ? '00'::text) Heap Blocks: exact=3438 -> Bitmap Index Scan on idxgintag (cost=0.00..19.50 rows=1000 width=0) (actual time=1.176..1.176 rows=3878 loops=1) Index Cond: ((jsonb_colmun -> 'value1'::text) ? '00'::text) Planning Time: 0.150 ms Execution Time: 23.939 ms (7 rows) ãªãã確èªããŠã¿ãã®ã§ããjsonã®å
容ãtextåã§è¿ããã ->> ãšããæŒç®åã䜿çšããå Žåã«ã¯ãindexã¯äœ¿çšãããªãããã§ã(åœããåãšããã°åœããåã§ãã)ã SELECT * FROM testjsonb WHERE (jsonb_colmun->>'value1') = '00'; å³èŸºã®jsonbãå«ããã©ãã indexãªãã§æ€çŽ¢ãè¡ãå Žåã EXPLAIN ANALYZE SELECT * FROM testjsonb WHERE jsonb_colmun @> '{"value1":"00"}'::jsonb; QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------ Gather (cost=1000.00..21693.33 rows=1000 width=92) (actual time=0.368..155.156 rows=3878 loops=1) Workers Planned: 2 Workers Launched: 2 -> Parallel Seq Scan on testjsonb (cost=0.00..20593.33 rows=417 width=92) (actual time=0.184..151.480 rows=1293 loops=3) Filter: (jsonb_colmun @> '{"value1": "00"}'::jsonb) Rows Removed by Filter: 332041 Planning Time: 0.034 ms Execution Time: 155.405 ms (8 rows) jsonb_path_opsãéžæããŠGINã貌ããš @> æ€çŽ¢ãé«éåããŸãã DROP INDEX IF EXISTS idxginp; CREATE INDEX idxginp ON testjsonb USING GIN (jsonb_colmun jsonb_path_ops); ANALYZE testjsonb; EXPLAIN ANALYZE SELECT * FROM testjsonb WHERE jsonb_colmun @> '{"value1":"00"}'::jsonb; QUERY PLAN ----------------------------------------------------------------------------------------------------------------------- Bitmap Heap Scan on testjsonb (cost=27.75..3186.69 rows=1000 width=92) (actual time=1.390..6.162 rows=3878 loops=1) Recheck Cond: (jsonb_colmun @> '{"value1": "00"}'::jsonb) Heap Blocks: exact=3438 -> Bitmap Index Scan on idxginp (cost=0.00..27.50 rows=1000 width=0) (actual time=0.606..0.606 rows=3878 loops=1) Index Cond: (jsonb_colmun @> '{"value1": "00"}'::jsonb) Planning Time: 0.140 ms Execution Time: 6.437 ms (7 rows) ããŒã¯ãŒãæ€çŽ¢ jsonbã®äœ¿ãæ¹ïœ¥ïœ¥ïœ¥ãšããããã§ã¯ãããŸããããäžéšã®valueã«éšåäžèŽæ€çŽ¢ãããããšãã¯ã以äžã®ããã«ããŠpg_bigm indexã䜿çšããããšãã§ããŸãã DROP EXTENSION IF EXISTS pg_bigm CASCADE; DROP INDEX IF EXISTS idx_pg_bigm; CREATE EXTENSION pg_bigm; CREATE INDEX idx_pg_bigm ON testjsonb USING gin (((jsonb_colmun->>'value2')) gin_bigm_ops); ANALYZE testjsonb; EXPLAIN ANALYZE SELECT * FROM testjsonb WHERE (jsonb_colmun->>'value2') like '%abcd%'; QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------ Bitmap Heap Scan on testjsonb (cost=126.00..13407.36 rows=8000 width=92) (actual time=21.786..39.752 rows=424 loops=1) Recheck Cond: ((jsonb_colmun ->> 'value2'::text) ~~ '%abcd%'::text) Rows Removed by Index Recheck: 2311 Heap Blocks: exact=2488 -> Bitmap Index Scan on idx_pg_bigm (cost=0.00..124.00 rows=8000 width=0) (actual time=21.103..21.103 rows=2735 loops=1) Index Cond: ((jsonb_colmun ->> 'value2'::text) ~~ '%abcd%'::text) Planning Time: 0.251 ms Execution Time: 39.804 ms (8 rows) ããããã®ã€ã³ããã¯ã¹ãµã€ãºã¯ä»¥äžã®éãã§ãã SELECT indexname ,pg_relation_size(indexname::regclass)/(1024*1024) as mbyte -- ããŒã¿ãµã€ãºãmbyteåäœã§è¡šç€º FROM pg_indexes WHERE schemaname = 'public' and indexname like 'idx%'; indexname | mbyte -------------+------- idxgin | 139 idxgintag | 2 idxginp | 69 idx_pg_bigm | 38 (4 rows) ã€ã³ããã¯ã¹ãµã€ãºã¯ã±ãŒã¹ãã€ã±ãŒã¹ãªã®ã§ããŸãããŠã«ã¯ãªããŸãããããåèãŸã§ã«ã (ä»åã¯è±æ°åã®ä¹±æ°ã®ã«ã©ã ã䜿ã£ãŠããŸãããbigmã€ã³ããã¯ã¹ã貌ã察象ãšããŠæ¥æ¬èªã䜿ããš2æååã®çµã¿åãããå¢å€§ããŠããŸããŸãããjsonã®æ§é ãè€éã«ãªãã»ã©ä»ã®indexãå¢å ããŠãããŸãã) jsonpathæŒç®å jsonpathæŒç®åã¯jsonã®ãªããžã§ã¯ããã£ãŒã«ãã«ã¢ã¯ã»ã¹ããèšæ³ã®äžã€ã§ãã ããã䜿ã£ãŠãç°¡åãªãã£ã«ã¿ãŒåŒïŒæ¯èŒæŒç®åãè«çæŒç®åãååšã®ãã§ãã¯ããã¿ãŒã³ããã ãªã©ïŒãçµãŠåŸãããå€ãé
åã«ãç°¡åãªåŠçïŒæ°åŠçåŠçãkeyvalueïŒãå ãããã®ãååŸã§ããŸãããã£ã«ã¿ãªã³ã°ã«ã¯indexãé©çšãããŸãã èšæ³ã¯ããJavaScriptå¯ãã§ããç䟡æŒç®åã§ãã£ã«ã¿ãªã³ã°ããŠã¿ãŸããç䟡æŒç®å㯠== ãšãªã£ãŠãããããŸãã(ãªãå³å¯ç䟡æŒç®å === ã¯äœ¿çšã§ããŸãã) ãé
åã¯ã€ã³ããã¯ã¹ã1ããå§ãŸããŸãã ãŸãã以äžã®äŸã®å Žåwhereå¥ãæžããŠããªãã§ããããã¹ãŠã®ãã£ã«ã¿ãŒåŒã«åœå€ãè¿ãã¬ã³ãŒãã¯èœã¡ãŠããŸããŸãã SELECT idx, jsonb_path_query(jsonb_colmun, '$[*]?(@.value1 == "00").value2') -- ãããã¬ãã«ããŒvalue1 == "00" ã®ã¬ã³ãŒãã®value2ãååŸããã FROM testjsonb ORDER BY idx LIMIT 5 ; idx | jsonb_path_query ------+------------------------------------ 168 | "006f52e9102a8d3be2fe5614f42ba989" 363 | "00411460f7c92d2124a67ea0f4cb5f85" 381 | "00ec53c4682d36f5c4359f4ae7bd7ba1" 610 | "00ac8ed3b4327bdd4ebbebcb2ba10a00" 1164 | "00e26af6ac3b1c1c49d7c3d79c60d000" (5 rows) SELECT idx ,jsonb_path_query(jsonb_colmun, '$[*]?(@.value1 == "00").value2') -- value1 == "00" ã®ã¬ã³ãŒãã®value2ãååŸããã ,jsonb_path_query(jsonb_colmun, '$[*]?(@.value1 == "01").value2') -- value1 == "01" ã®ã¬ã³ãŒãã®value2ãååŸããã FROM testjsonb ORDER BY idx LIMIT 5 ; idx | jsonb_path_query | jsonb_path_query -----+------------------------------------+------------------------------------ 138 | | "013d407166ec4fa56eb1e1f8cbe183b9" 168 | "006f52e9102a8d3be2fe5614f42ba989" | 236 | | "01161aaa0b6d1345dd8fe4e481144d84" 348 | | "01386bd6d8e091c2ab4c7c7de644d37b" 363 | "00411460f7c92d2124a67ea0f4cb5f85" | (5 rows) jsonbã®åºæ¬çãªæäœã¯ãããŸã§ã§ãã jsonpathåŒã¯è¥å¹²filiteråŒã«çœ ããããŸãããåºæ¬çãªæäœãåºæã£ãŠããããã§ããã 䜿çšã«ã€ããŠã®å±æ jsonãªããžã§ã¯ããé
åã«äœã§ãããŒã¿ãçªã£èŸŒãã®ã¯ãSQLã®ã¢ã³ããã¿ãŒã³ã«ã»ããªããŸããã ããã«æžããŠããããšã ãã§ããã£ããã¢ããããã®ã¯é¢åã§ããããããããšçœ ãããããšãèŠããŠããŠããŸãã CSVã¢ãŒãã§åã蟌ãéã«ã¯ã工倫ãèŠããŸããã工倫ãããããšèªäœããã°ã®æž©åºã®ããã«æããŸãã jsonpathããèªåãæ
åœããŠããã¢ããªã«æ°ããæ
åœè
ãä»ããæãªã©ããããªããšçè§£ããã¹ãç¯ããéçšããŠãããã®ã¯é£ãããšæããŸããã ãã ã以äžã®ãããªæ¡ä»¶ãå
ŒãããããŠããå Žåã¯æå¹ã«äœ¿ããã®ã§ã¯ãªãããšæããŸããã SQLäžã§ã«ã©ã ããjsonãçµã¿ç«ãŠãwebã¢ããªã§äœ¿çšãã 玹ä»ãããã¿ãŒã³ã«ãããŸããcsvãtxtãåã蟌ãã§jsonbãäœãå Žåãã«ã©ã ã®åãã§ãã¯ãåŠ¥åœæ§ã®è©äŸ¡ãäœåãªæåã®æé€ãªã©ãå¹ããŸããããŸãtsvãcsvãåã蟌ã¿ãã¢ããªã§äœ¿çšãã圢ã«çµã¿ç«ãŠãåã«ã¯ããã®ã§ã¯ãªãã§ãããã ç§èªèº«ã®çµéšã§ã¯ãjsonãè¿ãã¯ãã®APIã®è¿åŽå€ãåã蟌ãã§DBã«æ ŒçŽããããšããéã«ãå®éã«ã¯è¿åŽå€ãjsonã«ãªã£ãŠãããåã蟌ã¿ã«å€±æããçµéšããããŸã åçŽãªjsonãåºåããïŒèšãæããã°ä»¥äžã®ãããªã¢ã³ããã¿ãŒã³ãããããã§ãïŒ å€éšãã¡ã€ã«ã®csv, tsvãjsonbåãšããŠCOPYã³ãã³ãã§åã蟌ã 人ããã§ãã¯ããããšãå°é£ã«ãªãããã¹ãçãŸãããããªããã ãªãã§ãããã§ãjsonã«ããŠããŸã è€éãªjsonæ§é ã«ããŠããŸã äŸãã°ã§ãããç§ãæ
åœããŠããå®¿æšªææ€çŽ¢ã¢ããªãªã©ã®å Žåãå®¿æ³æœèšããŒã¿ç®¡çäžã®ã€ã¡ãŒãžç»åïŒurlãšç»åã¿ã€ãã®2ã€ã®æ
å ±ããããæ°ã¯æœèšããšã«ãŸã¡ãŸã¡ïŒãjsonbãšããŠæã€ã®ã¯ãããšæããŸããã pathãšvalueã®çµã¿åããã§ããæäœããããšããªãããã¿ãŒã³ããããªã©ããããã·ã³ãã«ã§ãã ãããã£ãç»åçšã®ããŒãã«ãªã©ãçšæããã®ãäžèŠã ãšæããéã«ã¯è¯ããšæããŸãã { imageNum: 4, images [ { "url" : "https://domain.co.jp/image/hotelXXXX/gaikan.gif", "type" : "å€èг" },{ "url" : "https://domain.co.jp/image/hotelXXXX/huro.gif", "type" : "济宀" },{ "url" : "https://domain.co.jp/image/hotelXXXX/heya1.gif", "type" : "宀å
" },{ "url" : "https://domain.co.jp/image/hotelXXXX/dinner.gif", "type" : "é£äº" } ] } ãããã£ãéžæè¢ã¯æã£ãŠããããšèªäœã匷ãã®ã§ãä¹±çšããã«äœ¿ããç¯å²ã§äœ¿çšããŠããããã§ããïŒ