PostgreSQL中如何使用jsonb数据类型,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。

PostgreSQL 9.4 正在加载一项新功能叫jsonb,是一种新型资料,可以储存支援GIN索引的JSON 资料。换言之,此功能,在即将来临的更新中最重要的是,如果连这都不重要的话,那就把Postgres 置于文件为本数据库系统的推荐位置吧。

自从9.2开始,一个整合JSON 资料类型已经存在,带有一整套功能(例如资料产生和资料解构功能),还有9.3新增的操作者。当使用JSON 资料类型,资料的被存储成一完全一样的副本,功能还在此之上运作,还另外需要后台运作的重新分析。

这心得JSONB 资料类型以已降解的2元格式存储,所以,插入此资料会比JSON高效,因为后台不再需要重新分析,因此让它更快速运行,而且还兼顾GIN 索引。就是因为最后这个原因,我们实际上建议读者使用jsonb来代替json制作程式(当然你还可以因应需要而使用json)。请记住jsonb使用相同的操作者和功能,读者们可以看我之前的帖子去令你得到些什么启发(或者干脆看Postgres的文件)。

现在让我们看一下JSONB是如何工作的,同时和JSON比较一下。采用的测试数据是860万的geobase类型数据,大概1.1G大小,包括了城市名,国家代码(可以在这参见完整列表)等很多字段。首先通过底层复制(raw copy)来把这些数据存储到数据库的一个新表里面,之后把这张表通过一组填充因子是100的表转换成JSON/JSONB,之后来看它们各占多少空间。

=#COPYgeodataFROM'$HOME/Downloads/allCountries.txt';COPY8647839=#CREATETABLEgeodata_jsonb(datajsonb)with(fillfactor=100);CREATETABLE=#CREATETABLEgeodata_json(datajson)with(fillfactor=100);CREATETABLE=#\timingTimingison.=#INSERTINTOgeodata_jsonSELECTrow_to_json(geodata)FROMgeodata;INSERT08647839Time:287158.457ms=#INSERTINTOgeodata_jsonbSELECTrow_to_json(geodata)::jsonbFROMgeodata;INSERT08647839Time:425825.967ms

生成JSONB数据花费稍微长一点时间,大小有没有区别呢?

=#SELECTpg_size_pretty(pg_relation_size('geodata_json'::regclass))ASjson,pg_size_pretty(pg_relation_size('geodata_jsonb'::regclass))ASjsonb;json|jsonb---------+---------3274MB|3816MB(1row)

在JSON数据上面做索引从9.3版本开始,比如用操作符(注意 因为它返回文本,所以'->>'被采用;并且根据查询不同,索引采用不同的关键字)

=#CREATEINDEXgeodata_indexONgeodata_json((data->>'country_code'),(data->>'asciiname'));CREATEINDEX=#SELECTpg_size_pretty(pg_relation_size('geodata_index'::regclass))ASjson_index;json_index------------310MB(1row)=#SELECT(data->>'population')::intaspopulation,data->'latitude'aslatitude,data->'longitude'aslongitudeFROMgeodata_jsonWHEREdata->>'country_code'='JP'ANDdata->>'asciiname'='Tokyo'AND(data->>'population')::int!=0;population|latitude|longitude------------+----------+-----------8336599|35.6895|139.69171(1row)=#--ExplainofpreviousqueryQUERYPLAN-------------------------------------------------------------------------------------------------------------------------BitmapHeapScanongeodata_json(cost=6.78..865.24rows=215width=32)RecheckCond:(((data->>'country_code'::text)='JP'::text)AND((data->>'asciiname'::text)='Tokyo'::text))Filter:(((data->>'population'::text))::integer<>0)->BitmapIndexScanongeodata_index(cost=0.00..6.72rows=216width=0)IndexCond:(((data->>'country_code'::text)='JP'::text)AND((data->>'asciiname'::text)='Tokyo'::text))Planningtime:0.172ms(6rows)

在这个例子里,计划(planner)可以使用bitmap索引扫描,同时使用了之前产生的索引。


现在,JSONB的一个新特点就是检查包含带有操作符@>的数据容量,这种数据是可以用GIN来索引的,这种操作符数据也包括了?,?|和?&(为了检查给定的关键字是否存在)。 GIN索引对两类操作符起作用:

缺省操作符类,之前列出的四个;

jsonb_hash_ops,仅支持@>,但是当搜索数据时性能表现不错,而且所占磁盘空间较小;

下面是它如何工作:

=#CREATEINDEXgeodata_ginONgeodata_jsonbUSINGGIN(datajsonb_hash_ops);CREATEINDEX=#SELECT(data->>'population')::intaspopulation,data->'latitude'aslatitude,data->'longitude'aslongitudeFROMgeodata_jsonbWHEREdata@>'{"country_code":"JP","asciiname":"Tokyo"}'AND(data->>'population')::int!=0;population|latitude|longitude------------+----------+-----------8336599|35.6895|139.69171(1row)=#SELECTpg_size_pretty(pg_relation_size('geodata_gin'::regclass))ASjsonb_gin;jsonb_gin-----------1519MB(1row)=#--EXPLAINofpreviousqueryQUERYPLAN-------------------------------------------------------------------------------------BitmapHeapScanongeodata_jsonb(cost=131.01..31317.76rows=8605width=418)RecheckCond:(data@>'{"asciiname":"Tokyo","country_code":"JP"}'::jsonb)Filter:(((data->>'population'::text))::integer<>0)->BitmapIndexScanongeodata_gin(cost=0.00..128.86rows=8648width=0)IndexCond:(data@>'{"asciiname":"Tokyo","country_code":"JP"}'::jsonb)Planningtime:0.134ms

根据应用的需求,你或许想采用空间消耗低的索引,比如BTree建立在JSON数据上的索引类型;GIN索引有着更多的优点,因为它覆盖了所有的JSON字段,并且检查容量;

关于PostgreSQL中如何使用jsonb数据类型问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注亿速云行业资讯频道了解更多相关知识。