json,jsonb区别
json和jsonb,而两者唯一的区别在于效率,json是对输入的完整拷贝,使用时再去解析,所以它会保留输入的空格,重复键以及顺序等。而jsonb是解析输入后保存的二进制,它在解析时会删除不必要的空格和重复的键,顺序和输入可能也不相同。使用时不用再次解析。两者对重复键的处理都是保留最后一个键值对。效率的差别:json类型存储快,查询慢,jsonb类型存储稍慢,查询较快(支持许多额外的操作符)。
关于json和jsonb存储和解析效率连接
这里主要测试jsonb的增删改查
json和jsonb共同操作符
| 操作符 | 返回类型 | 数组[1,2,3] | {“a”:1,”b”:2,”c”:3} | {“a”:{“b”:{“c”:1}},”d”:[4,5,6]} |
|---|---|---|---|---|
| -> | json | select ‘[1,2,3]’::jsonb ->2 = 3 | select ‘{“a”:1,”b”:2,”c”:3}’::jsonb-> ‘a’=1 | select ‘{“a”:{“b”:{“c”:1}},”d”:[4,5,6]}’::jsonb ->’a’={“b”: {“c”: 1}} |
| ->> | text | select ‘[1,2,3]’::jsonb ->>2 = 3 | select ‘{“a”:1,”b”:2,”c”:3}’::jsonb->> ‘a’=1 | select ‘{“a”:{“b”:{“c”:1}},”d”:[4,5,6]}’::jsonb ->>’a’={“b”: {“c”: 1}} |
| #> | json | — | — | select ‘{“a”:{“b”:{“c”:1}},”d”:[4,5,6]}’::jsonb #> ‘{a,b}’ ={“c”: 1} |
| #>> | text | — | — | select ‘{“a”:{“b”:{“c”:1}},”d”:[4,5,6]}’::jsonb #> ‘{a,b}’ ={“c”: 1} |
jsonb额外操作符
| 操作符 | 右操作数类型 | 描述 | 例子 | ||||
|---|---|---|---|---|---|---|---|
| @> | jsonb | 左边的 JSON 值是否包含顶层右边JSON路径/值项? | ‘{“a”:1, “b”:2}’::jsonb @> ‘{“b”:2}’::jsonb | ||||
| <@ | jsonb | 左边的JSON路径/值是否包含在顶层右边JSON值中? | ‘{“b”:2}’::jsonb <@ ‘{“a”:1, “b”:2}’::jsonb | ||||
| ? | text | 字符串是否作为顶层键值存在于JSON值中? | ‘{“a”:1, “b”:2}’::jsonb ? ‘b’ | ||||
| ? | text[] | 这些数组字符串中的任何一个是否作为顶层键值存在? | ‘{“a”:1, “b”:2, “c”:3}’::jsonb ? | array[‘b’,c’] | |||
| ?& | text[] | 这些数组字符串是否作为顶层键值存在? | ‘[“a”, “b”]’::jsonb ?& array[‘a’, ‘b’] | ||||
| jsonb | 连接两个jsonb值到新的jsonb值 | ‘[“a”, “b”]’::jsonb | ‘[“c”, “d”]’::jsonb | ||||
| - | text | 从左操作数中删除键/值对或字符串元素。基于键值匹配键/值对。 | ‘{“a”: “b”}’::jsonb - ‘a’ | ||||
| - | integer | 删除指定索引的数组元素(负整数结尾)。如果顶层容器不是一个数组,那么抛出错误。 | ‘[“a”, “b”]’::jsonb - 1 | ||||
| #- | text[] | 删除指定路径的域或元素(JSON数组,负整数结尾) | ‘[“a”, {“b”:1}]’::jsonb #- ‘{1,b}’ |
jsonb增删改
--1.1建表a => create table test_jsonb(c_bh char(32),j_jsonb jsonb);CREATE TABLE--插入数据insert into test_jsonb(c_bh,j_jsonb) values(replace(uuid_generate_v4()::text,'-',''),'{"c_xm":"张三","c_mx":{"c_ssdw":"一大队","c_dwbm":"11"}}');INSERT 0 1--查看数据a =# select * from test_jsonb where j_jsonb @> '{"c_xm":"张三","c_mx":{"c_ssdw":"一大队","c_dwbm":"11"}}';c_bh | j_jsonb----------------------------------+--------------------------------------------c217c624152943ab93f502117514f432 | {"c_mx": {"c_dwbm": "11", "c_ssdw": "一大队"}, "c_xm": "张三"}(1 row)--1.2操作符||可用于添加元素,添加元素'{"c_id":"111"}'a =# update test_jsonb set j_jsonb = j_jsonb ||'{"c_id":"111"}'::jsonb where c_bh = 'c217c624152943ab93f502117514f432';UPDATE 1a =# select j_jsonb from test_jsonb where c_bh = 'c217c624152943ab93f502117514f432';j_jsonb-------------------------------------------------------------------------------{"c_id": "111", "c_mx": {"c_dwbm": "11", "c_ssdw": "一大队"}, "c_xm": "张三"}(1 row)--1.3更新元素(方法1),如果jsonb中有相同的元素则覆盖,使用'||'将'{"c_id":"111"}'更新为112a =# update test_jsonb set j_jsonb = j_jsonb ||'{"c_id":"112"}'::jsonb where c_bh = 'c217c624152943ab93f502117514f432';UPDATE 1a =# select j_jsonb from test_jsonb where c_bh = 'c217c624152943ab93f502117514f432';j_jsonb-------------------------------------------------------------------------------{"c_id": "112", "c_mx": {"c_dwbm": "11", "c_ssdw": "一大队"}, "c_xm": "张三"}(1 row)--更新元素(方法2),使用jsonb_set,将"c_id": "112"更新为123a =# update test_jsonb set j_jsonb= jsonb_set(j_jsonb,'{c_id}','"123"'::jsonb,false) where c_bh = 'c217c624152943ab93f502117514f432';UPDATE 1a =# select j_jsonb from test_jsonb where c_bh = 'c217c624152943ab93f502117514f432';j_jsonb-------------------------------------------------------------------------------{"c_id": "123", "c_mx": {"c_dwbm": "11", "c_ssdw": "一大队"}, "c_xm": "张三"}(1 row)--1.4更新嵌套元素,使用jsonb_set(pg9.5以上才支持),更新c_ssdw为二大队a =# update test_jsonb set j_jsonb= jsonb_set(j_jsonb,'{c_mx,c_ssdw}','"二大队"'::jsonb,false) where c_bh = 'c217c624152943ab93f502117514f432';UPDATE 1a =# select j_jsonb from test_jsonb where c_bh = 'c217c624152943ab93f502117514f432';j_jsonb-------------------------------------------------------------------------------{"c_id": "123", "c_mx": {"c_dwbm": "11", "c_ssdw": "二大队"}, "c_xm": "张三"}(1 row)--1.5删除元素,删除c_id元素a =# update test_jsonb set j_jsonb = j_jsonb-'c_id' where c_bh = 'c217c624152943ab93f502117514f432' ;UPDATE 1a =# select j_jsonb from test_jsonb where c_bh = 'c217c624152943ab93f502117514f432';j_jsonb----------------------------------------------------------------{"c_mx": {"c_dwbm": "11", "c_ssdw": "二大队"}, "c_xm": "张三"}(1 row)
jsonb查询
--1.随机文本脚本a => create or replace function random_string(INTEGER)a -> RETURNS TEXT ASa -> $BODY$a $> select array_to_string(a $> array(a $> select substring(a $> 'pg社区的作风非常严谨,一个补丁可能在邮件组中讨论几个月甚至几年,根据大家的意见反复的修正,补丁合并到主干已经非常成熟,所以pg的稳定性也是远近闻名的'a $> from (ceil(random()*73))::int FOR 2a $> )a $> from generate_series(1,$1)a $> ),''a $> ) $BODY$a -> LANGUAGE sql VOLATILE;CREATE FUNCTION--2.初始化数据:a => insert into test_jsonb select replace(uuid_generate_v4()::text,'-',''),('{"a":'||random()*100||', "kxhbsl":"'|| random_string(10) ||'"}')::jsonb from generate_series(1,2000000);INSERT 0 2000000a => insert into test_jsonb select replace(uuid_generate_v4()::text,'-',''),('{"a":'||random()*100||', "kxhbsl":"索尼是大法官"}')::jsonb from generate_series(1,10000);INSERT 0 10000--3.第一种查询:获取包含'{"kxhbsl": "索尼是大法官"}',全表扫描a =# explain analyze select j_jsonb->>'kxhbsl',j_jsonb from test_jsonb where j_jsonb @> '{"kxhbsl": "索尼是大法官"}';QUERY PLAN-------------------------------------------------------------------------------------------------------------Gather (cost=1000.00..53379.78 rows=2010 width=134) (actual time=470.729..490.979 rows=10000 loops=1)Workers Planned: 2Workers Launched: 2-> Parallel Seq Scan on test_jsonb (cost=0.00..52175.85 rows=838 width=134) (actual time=465.234..480.573 rows=3333 loops=3)Filter: (j_jsonb @> '{"kxhbsl": "索尼是大法官"}'::jsonb)Rows Removed by Filter: 666667Planning time: 0.318 msExecution time: 506.204 ms(8 rows)--j_jsonb字段创建gin索引后,可走索引a =# create index i_t_test_jsonb_j_jsonb on test_jsonb using gin(j_jsonb);CREATE INDEXa =# explain analyze select j_jsonb->>'kxhbsl',* from test_jsonb where j_jsonb @> '{"kxhbsl": "索尼是大法官"}';QUERY PLAN-------------------------------------------------------------------------------------------------------------Bitmap Heap Scan on test_jsonb (cost=59.58..6664.09 rows=2010 width=167) (actual time=3.579..17.065 rows=10000 loops=1)Recheck Cond: (j_jsonb @> '{"kxhbsl": "索尼是大法官"}'::jsonb)Heap Blocks: exact=481-> Bitmap Index Scan on i_t_test_jsonb_j_jsonb (cost=0.00..59.08 rows=2010 width=0) (actual time=3.480..3.480 rows=10000 loops=1)Index Cond: (j_jsonb @> '{"kxhbsl": "索尼是大法官"}'::jsonb)Planning time: 0.429 msExecution time: 17.964 ms(7 rows)--4.第二种查询,获取包含:'索尼是大法官',全表扫描a =# explain analyze select j_jsonb->>'kxhbsl',j_jsonb from test_jsonb where j_jsonb -> 'kxhbsl' ? '索尼是大法官';QUERY PLAN-------------------------------------------------------------------------------------------------------------Gather (cost=1000.00..55473.53 rows=2010 width=134) (actual time=1724.170..1769.543 rows=10000 loops=1)Workers Planned: 2Workers Launched: 0-> Parallel Seq Scan on test_jsonb (cost=0.00..54269.60 rows=838 width=134) (actual time=1723.752..1767.187 rows=10000 loops=1)Filter: ((j_jsonb -> 'kxhbsl'::text) ? '索尼是大法官'::text)Rows Removed by Filter: 2000000Planning time: 0.267 msExecution time: 1770.422 ms(8 rows)--针对jsonb字段的kxhbsl元素创建gin索引。 可走索引a =# create index i_t_test_jsonb_j_jsonb_kxhbsl on test_jsonb using gin((j_jsonb->'kxhbsl'));CREATE INDEXa =# explain analyze select j_jsonb->>'kxhbsl',j_jsonb from test_jsonb where j_jsonb -> 'kxhbsl' ? '索尼是大法官';QUERY PLAN-------------------------------------------------------------------------------------------------------------Bitmap Heap Scan on test_jsonb (cost=39.58..6649.12 rows=2010 width=134) (actual time=2.166..13.999 rows=10000 loops=1)Recheck Cond: ((j_jsonb -> 'kxhbsl'::text) ? '索尼是大法官'::text)Heap Blocks: exact=481-> Bitmap Index Scan on i_t_test_jsonb_j_jsonb_kxhbsl (cost=0.00..39.08 rows=2010 width=0) (actual time=2.045..2.045 rows=10000 loops=1)Index Cond: ((j_jsonb -> 'kxhbsl'::text) ? '索尼是大法官'::text)Planning time: 0.221 msExecution time: 14.715 ms(7 rows)--或者等价写法:a =# explain analyze select j_jsonb->>'kxhbsl',j_jsonb from test_jsonb where j_jsonb -> 'kxhbsl' @>'"索尼是大法官"';QUERY PLAN-------------------------------------------------------------------------------------------------------------Bitmap Heap Scan on test_jsonb (cost=39.58..6649.12 rows=2010 width=134) (actual time=2.080..14.959 rows=10000 loops=1)Recheck Cond: ((j_jsonb -> 'kxhbsl'::text) @> '"索尼是大法官"'::jsonb)Heap Blocks: exact=481-> Bitmap Index Scan on i_t_test_jsonb_j_jsonb_kxhbsl (cost=0.00..39.08 rows=2010 width=0) (actual time=1.980..1.980 rows=10000 loops=1)Index Cond: ((j_jsonb -> 'kxhbsl'::text) @> '"索尼是大法官"'::jsonb)Planning time: 0.199 msExecution time: 15.635 ms(7 rows)--5.第三种查询,获取'{"kxhbsl": "索尼是大法官"}',全表扫描a =# explain analyze select * from test_jsonb where j_jsonb->>'kxhbsl' = '索尼是大法官';QUERY PLAN-------------------------------------------------------------------------------------------------------------Gather (cost=1000.00..56272.50 rows=10050 width=135) (actual time=458.676..476.454 rows=10000 loops=1)Workers Planned: 2Workers Launched: 2-> Parallel Seq Scan on test_jsonb (cost=0.00..54267.50 rows=4188 width=135) (actual time=453.472..466.544 rows=3333 loops=3)Filter: ((j_jsonb ->> 'kxhbsl'::text) = '索尼是大法官'::text)Rows Removed by Filter: 666667Planning time: 0.821 msExecution time: 492.763 ms(8 rows)--针对这类查询,j_jsonb->>'kxhbsl'返回类型为text,那么可以考虑创建一个btree索引,也可以走索引a =# create index i_test_jsonb_j_jsonb_btree on test_jsonb using btree((j_jsonb ->> 'kxhbsl') );CREATE INDEXa =# explain analyze select * from test_jsonb where j_jsonb->>'kxhbsl' = '索尼是大法官';QUERY PLAN-------------------------------------------------------------------------------------------------------------Bitmap Heap Scan on test_jsonb (cost=498.44..24049.15 rows=10050 width=135) (actual time=4.150..8.168 rows=10000 loops=1)Recheck Cond: ((j_jsonb ->> 'kxhbsl'::text) = '索尼是大法官'::text)Heap Blocks: exact=481-> Bitmap Inde
继续阅读与本文标签相同的文章
上一篇 :
高级Java面试总结
-
技术人看《长安十二时辰》的正确姿势是?
2026-05-18栏目: 教程
-
使用logrotate切割日志
2026-05-18栏目: 教程
-
网站漏洞检测 apache nginx解析绕过上传漏洞
2026-05-18栏目: 教程
-
渗透测试 网站安全基础点web讲解(第一点)
2026-05-18栏目: 教程
-
【阿里云新品发布·周刊】第26期:硬核!阿里云新品动态一手掌握
2026-05-18栏目: 教程
