PG json/jsonb简单性能测试
读写性能测试:
-
200万行数据写入对比:
postgres@findb:create table user_ini(id int4,user_id int8,user_name varchar(64),create_time timestamp default clock_timestamp());
CREATE TABLE
postgres@findb:\d user_ini
Table "public.user_ini"
Column | Type | Collation | Nullable | Default
-------------+-----------------------------+-----------+----------+-------------------
id | integer | | |
user_id | bigint | | |
user_name | character varying(64) | | |
create_time | timestamp without time zone | | | clock_timestamp()
postgres@findb:insert into user_ini(id,user_id,user_name)
findb-# select r,round(random()*2000000),r||'_leadx'
findb-# from generate_series(1,2000000) as r;
INSERT 0 2000000
postgres@findb:\dt+ user_ini
List of relations
Schema | Name | Type | Owner | Size | Description
--------+----------+-------+----------+--------+-------------
public | user_ini | table | postgres | 130 MB |
(1 row)
postgres@findb:select count(*) from user_ini ;
count
---------
2000000
(1 row)
postgres@findb:create table tbl_user_json(id serial,userinfo json);
CREATE TABLE
postgres@findb:create table tbl_user_jsonb(id serial,user_info jsonb);
CREATE TABLE
postgres@findb:\timing on
Timing is on.
postgres@findb:insert into tbl_user_json(userinfo) select row_to_json(user_ini) from user_ini;
INSERT 0 2000000
Time: 11461.166 ms (00:11.461)
postgres@findb:insert into tbl_user_jsonb(user_info) select row_to_json(user_ini) from user_ini;
INSERT 0 2000000
Time: 23366.464 ms (00:23.366)
postgres@findb:\dt+
List of relations
Schema | Name | Type | Owner | Size | Description
--------+----------------+-------+----------+------------+-------------
public | tbl_user_json | table | postgres | 269 MB |
public | tbl_user_jsonb | table | postgres | 326 MB |
public | user_ini | table | postgres | 130 MB |
(3 rows)
可见相同200万的数据,json写入耗时11.46秒,jsonb写入耗时23.36秒,并且jsonb的体积326M也比json的269M略大
-
200万行数据读取测试
postgres@findb:explain analyze select * from tbl_user_jsonb where user_info->>'user_name'='1_leadx';
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------------------
Gather (cost=1000.00..56173.49 rows=10000 width=136) (actual time=58.207..2721.276 rows=1 loops=1)
Workers Planned: 2
Workers Launched: 2
-> Parallel Seq Scan on tbl_user_jsonb (cost=0.00..54173.49 rows=4167 width=136) (actual time=1740.873..2626.759 rows=0 loops=3)
Filter: ((user_info ->> 'user_name'::text) = '1_leadx'::text)
Rows Removed by Filter: 666666
Planning Time: 30.226 ms
Execution Time: 2721.788 ms
(8 rows)
postgres@findb:explain analyze select * from tbl_user_jsonb where user_info->>'user_name'='1_leadx';
QUERY PLAN
------------------------------------------------------------------------------------------------------------------------------------
Gather (cost=1000.00..56173.49 rows=10000 width=136) (actual time=0.489..395.663 rows=1 loops=1)
Workers Planned: 2
Workers Launched: 2
-> Parallel Seq Scan on tbl_user_jsonb (cost=0.00..54173.49 rows=4167 width=136) (actual time=256.120..386.660 rows=0 loops=3)
Filter: ((user_info ->> 'user_name'::text) = '1_leadx'::text)
Rows Removed by Filter: 666666
Planning Time: 0.115 ms
Execution Time: 395.698 ms
(8 rows)
postgres@findb:create index idx_jsonb on tbl_user_jsonb using btree((user_info->>'user_name'));
CREATE INDEX
postgres@findb:\di+
List of relations
Schema | Name | Type | Owner | Table | Size | Description
--------+---------------+-------+----------+----------------+-------+-------------
public | idx_jsonb | index | postgres | tbl_user_jsonb | 60 MB |
public | score_pkey | index | fin_er | score | 16 kB |
public | tbl_json_gin | index | postgres | tbl_json | 24 kB |
public | tbl_mvcc_pkey | index | postgres | tbl_mvcc | 16 kB |
(4 rows)
postgres@findb:explain analyze select * from tbl_user_jsonb where user_info->>'user_name'='1_leadx';
QUERY PLAN
----------------------------------------------------------------------------------------------------------------------------
Bitmap Heap Scan on tbl_user_jsonb (cost=233.93..23700.60 rows=10000 width=136) (actual time=0.145..0.147 rows=1 loops=1)
Recheck Cond: ((user_info ->> 'user_name'::text) = '1_leadx'::text)
Heap Blocks: exact=1
-> Bitmap Index Scan on idx_jsonb (cost=0.00..231.43 rows=10000 width=0) (actual time=0.135..0.136 rows=1 loops=1)
Index Cond: ((user_info ->> 'user_name'::text) = '1_leadx'::text)
Planning Time: 0.300 ms
Execution Time: 0.287 ms
(7 rows)
第一次全扫描2.7秒,后续300多ms,在userinfo上针对创建索引后,降至0.287ms
Filter移除行数666666不对?
postgres@findb:create index idx_gin_user_info_id on tbl_user_json using btree(((userinfo->>'id')::integer));
CREATE INDEX
Time: 5671.853 ms (00:05.672)
postgres@findb:create index idx_gin_user_info_id1 on tbl_user_jsonb using btree(((user_info->>'id')::integer));
CREATE INDEX
Time: 3128.501 ms (00:03.129)
postgres@findb:\di+
List of relations
Schema | Name | Type | Owner | Table | Size | Description
--------+-----------------------+-------+----------+----------------+-------+-------------
public | idx_gin_user_info_id | index | postgres | tbl_user_json | 43 MB |
public | idx_gin_user_info_id1 | index | postgres | tbl_user_jsonb | 43 MB |
public | idx_jsonb | index | postgres | tbl_user_jsonb | 60 MB |
public | score_pkey | index | fin_er | score | 16 kB |
public | tbl_json_gin | index | postgres | tbl_json | 24 kB |
public | tbl_mvcc_pkey | index | postgres | tbl_mvcc | 16 kB |
(6 rows)
postgres@findb:explain analyze select id,userinfo->'id',userinfo->'user_name' from tbl_user_json where (userinfo->>'id')::int4>1 and (userinfo->>'id')::int4<10000;
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------------------
Bitmap Heap Scan on tbl_user_json (cost=214.93..22291.91 rows=10000 width=68) (actual time=4.804..73.262 rows=9998 loops=1)
Recheck Cond: ((((userinfo ->> 'id'::text))::integer > 1) AND (((userinfo ->> 'id'::text))::integer < 10000))
Heap Blocks: exact=164
-> Bitmap Index Scan on idx_gin_user_info_id (cost=0.00..212.43 rows=10000 width=0) (actual time=3.626..3.626 rows=9998 loops=1)
Index Cond: ((((userinfo ->> 'id'::text))::integer > 1) AND (((userinfo ->> 'id'::text))::integer < 10000))
Planning Time: 2.478 ms
Execution Time: 74.730 ms
(7 rows)
postgres@findb:explain analyze select id,user_info->'id',user_info->'user_name' from tbl_user_jsonb where (user_info->>'id')::int4>1 and (user_info->>'id')::int4<10000;
QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------------------
Bitmap Heap Scan on tbl_user_jsonb (cost=214.93..23881.60 rows=10000 width=68) (actual time=1.325..24.342 rows=9998 loops=1)
Recheck Cond: ((((user_info ->> 'id'::text))::integer > 1) AND (((user_info ->> 'id'::text))::integer < 10000))
Heap Blocks: exact=193
-> Bitmap Index Scan on idx_gin_user_info_id1 (cost=0.00..212.43 rows=10000 width=0) (actual time=1.186..1.186 rows=9998 loops=1)
Index Cond: ((((user_info ->> 'id'::text))::integer > 1) AND (((user_info ->> 'id'::text))::integer < 10000))
Planning Time: 0.244 ms
Execution Time: 25.724 ms
(7 rows)
相同列上创建索引,索引大小相同,但明显jsonb读取更快导致索引创建时间更快,json:jsonb--5.67s:3.12s
走相同索引的查询,jsonb的也更快,json:jsonb--74.73ms:25.72 ms
-
总结,除纯索引扫描外,需要回表的情况下,jsonb的访问都比json快,但插入json较jsonb快