本文将为您介绍Hologres中JSON和JSONB数据类型的语法和使用方法。
使用限制
Hologres支持JSON和JSONB两种JSON数据类型,在使用时需要注意的事项如下:
- 仅Hologres V0.9及以上版本支持JSON类型,如果您的实例是V0.9以下版本,请您提交工单或加入在线支持钉钉群申请升级实例。
- 仅Hologres V1.1及以上版本支持JSONB类型创建GIN索引,如果您的实例是V1.1以下版本,请您提交工单或加入在线支持钉钉群申请升级实例。
- Hologres暂不支持的函数包括如下函数:json_each、jsonb_each、json_each_text、jsonb_each_text、json_extract_path、jsonb_extract_path、jsonb_to_record。
如果您需要使用jsonb_extract_path和json_extract_path函数可以使用如下等价写法。
SELECT json_extract_path( '{"key":{"key1":"key1","key2":"key2"}}'::json , 'key' , 'key1' ); --json_extract_path函数的等价写法如下 SELECT '{"key":{"key1":"key1","key2":"key2"}}'::json #> '{"key","key1"}';
SELECT jsonb_extract_path( '{"key":{"key1":"key1","key2":"key2"}}'::jsonb , 'key' , 'key1' ); -- jsonb_extract_path函数的等价写法如下 SELECT '{"key":{"key1":"key1","key2":"key2"}}'::jsonb #> '{"key","key1"}';
- 仅Hologres V1.3及以上版本支持对JSONB类型进行列存优化,若您的实例是V1.3以下版本,请您提交工单或加入在线支持钉钉群申请升级实例。
- JSONB的列存优化仅能用于列存表,行存表暂不支持,且至少1000条数据才会触发列存优化。
JSON和JSONB类型概述
JSON和JSONB区别如下。
- JSON储存的是文本格式的数据,JSONB储存的是Binary格式的数据。
- JSON插入速度快,查询速度慢,原因是处理函数必须在每次执行时重新解析该数据。JSONB插入速度慢,而查询速度快,原因是JSONB数据被存储在一种分解好的二进制格式中,因为需要做附加的转换,它在输入时要稍慢一些。但是JSONB在查询数据时快很多,因为不需要重新解析。
- JSON储存的数据是对数据的完整拷贝,会保留源数据的空格、重复键和顺序等,如果一个值中的JSON对象包含同一个键超过一次,所有的键、值对都会被保留。而JSONB在解析时会删除掉不必要的空格、重复键和数据的顺序等,如果在输入中指定了重复的键,只有最后一个值会被保留。
说明 键值对的键必须使用双引号。
JSON和JSONB的操作符
JSON数据类型用来存储JSON数据,这种数据也可以被存储为TEXT类型。JSON数据类型的优势在于能强制要求每个被存储的值符合JSON规则,JSON支持的操作符使得其操作更为方便。
操作符 | 右操作数类型 | 描述 | 操作示例 | 执行结果 |
---|---|---|---|---|
-> | int | 获得JSON数组元素(索引从0开始,负整数从末尾开始计)。 | select '[{"a":"foo"},{"b":"bar"},{"c":"baz"}]'::json->2 |
{"c":"baz"} |
-> | text | 通过键获得JSON对象域。 | select '{"a": {"b":"foo"}}'::json->'a' |
{"b":"foo"} |
->> | int | 以TEXT形式获得JSON数组元素。 | select '[1,2,3]'::json->>2 |
3 |
->> | text | 以TEXT形式获得JSON对象域。 | select '{"a":1,"b":2}'::json->>'b' |
2 |
#> | text[] | 获取在指定路径的JSON对象。 | select '{"a": {"b":{"c": "foo"}}}'::json#>'{a,b}' |
{"c":"foo"} |
#>> | text[] | 以TEXT形式获取在指定路径的JSON对象。 | select '{"a":[1,2,3],"b":[4,5,6]}'::json#>>'{a,2}' |
3 |
额外的JSONB操作符
如下表格中为JSONB数据类型支持的操作符。
操作符 | 右操作数类型 | 描述 | 操作示例 | 执行结果 |
---|---|---|---|---|
@> | jsonb | 左侧的JSON值是否在顶层包含右侧的JSON路径或值。 | select '{"a":1, "b":2}'::jsonb @> '{"b":2}'::jsonb |
true |
<@ | jsonb | 左侧的JSON路径或值项是否被包含在右侧的JSON 值的顶层。 | select '{"b":2}'::jsonb <@ '{"a":1, "b":2}'::jsonb |
true |
? | text | 键或元素字符串是否存在于JSON值的顶层。 | select '{"a":1, "b":2}'::jsonb ? 'b' |
true |
?| | text[] | 数组字符串中的任何一个是否做为顶层键存在。 | select '{"a":1, "b":2, "c":3}'::jsonb ?| array['b', 'c'] |
true |
?& | text[] | 是否所有数组字符串都作为顶层键存在。 | select '["a", "b"]'::jsonb ?& array['a', 'b'] |
true |
|| | jsonb | 将两个jsonb值串接成一个新的jsonb值。 | select '["a", "b"]'::jsonb || '["c", "d"]'::jsonb |
["a", "b", "c", "d"] |
- | text | 从左操作数删除键/值对或者string元素。键/值对基于它们的键值来匹配。 | select '{"a": "b"}'::jsonb - 'a' |
{} |
- | text[] | 从左操作数中删除多个键/值对或者string元素。键/值对基于它们的键值来匹配。 | select '{"a": "b", "c": "d"}'::jsonb - '{a,c}'::text[] |
{} |
- | integer | 删除具有指定索引(负值表示倒数)的数组元素。如果顶层容器不是数组则抛出一个错误。 | select '["a", "b"]'::jsonb - 1 |
["a"] |
#- | text[] | 删除具有指定路径的域或者元素(对于JSON数组,负值表示倒数)。 | select '["a", {"b":1}]'::jsonb #- '{1,b}' |
["a", {}] |
JSON创建函数
如下为可以用于创建JSON值的函数描述及操作示例。
函数 | 描述 | 操作示例 | 执行结果 |
---|---|---|---|
to_json(anyelement) | 此函数可以将该值返回为JSON。数组和组合会被(递归)转换成数组和对象,对于不是数组和组合的值,如果有从该类型到JSON的造型,造型函数将被用来执行该转换,否则将产生一个标量值。对于任何不是数字、布尔、空值的标量类型,将使用文本表达,使其是一个有效的JSON值。 | select to_json('Fred said "Hi."'::text) |
"Fred said \"Hi.\"" |
to_jsonb(anyelement) | |||
array_to_json(anyarray [, pretty_bool]) | 此函数可以将数组作为一个JSON数组返回。一个PostgreSQL多维数组会成为一个数组的JSON数组。如果pretty_bool为真,将在第1维度的元素之间增加换行。 | select array_to_json('{{1,5},{99,100}}'::int[]) |
[[1,5],[99,100]] |
json_build_array(VARIADIC "any") | 此函数可以从一个可变参数列表构造一个可能包含异质类型的JSON数组。 | select json_build_array(1,2,'3',4,5) |
[1, 2, "3", 4, 5] |
jsonb_build_array(VARIADIC "any") | |||
json_build_object(VARIADIC "any") | 此函数可以从一个可变参数列表构造一个JSON对象。通过转换,该参数列表由交替出现的键和值构成。 | select json_build_object('foo',1,'bar',2) |
{"foo": 1, "bar": 2} |
jsonb_build_object(VARIADIC "any") | |||
json_object(text[]) | 此函数可以从一个文本数组构造一个JSON对象。该数组必须可以是具有偶数个成员的一维数组(成员被当做交替出现的键/值对),或者是一个二维数组(每一个内部数组刚好有2个元素,可以被看做是键/值对)。 | select json_object('{a, 1, b, "def", c, 3.5}'); |
{"a": "1", "b": "def", "c": "3.5"} |
jsonb_object(text[]) | select jsonb_object('{a, 1, b, "def", c, 3.5}'); |
{"a": "1", "b": "def", "c": "3.5"} |
|
json_object(keys text[], values text[]) | json_object的这种形式从两个独立的数组得到键/值对。在其他方面和一个参数的形式相同。 | select json_object('{a, b}', '{1,2}') |
{"a": "1", "b": "2"} |
jsonb_object(keys text[], values text[]) |
JSON处理函数
如下为可以用于处理JSON值的函数描述及操作示例。
函数 | 返回值 | 描述 | 操作示例 | 执行结果 |
---|---|---|---|---|
json_array_length(json) | int | 返回最外层JSON数组中的元素数量。 | select json_array_length('[1,2,3,{"f1":1,"f2":[5,6]},4]') |
5 |
jsonb_array_length(jsonb) | ||||
json_object_keys(json) | setof text | 返回最外层JSON对象中的键集合。 | select json_object_keys('{"f1":"abc","f2":{"f3":"a", "f4":"b"}}') |
|
jsonb_object_keys(jsonb) | ||||
json_populate_record(base anyelement, from_json json) | anyelement | 扩展from_json中的对象成一个行,它的列匹配由base定义的记录类型。 |
|
|
jsonb_populate_record(base anyelement, from_json jsonb) | ||||
json_populate_recordset(base anyelement, from_json json) | setof anyelement | 扩展from_json中最外的对象数组为一个集合,该集合的列匹配由base定义的记录类型。 |
|
|
jsonb_populate_recordset(base anyelement, from_json jsonb) | ||||
json_array_elements(json) | setof json | 把一个JSON数组扩展成一个JSON值的集合。 | select * from json_array_elements('[1,true, [2,false]]') |
|
jsonb_array_elements(jsonb) | setof jsonb | |||
json_array_elements_text(json) | setof text | 把一个JSON数组扩展成一个text值集合。 | select * from json_array_elements_text('["foo", "bar"]') |
|
jsonb_array_elements_text(jsonb) | ||||
json_typeof(json) | text | 把最外层的JSON值的类型作为一个文本字符串返回。可能的类型是: object、array、string、number、 boolean以及null。 | select json_typeof('-123.4') |
number |
jsonb_typeof(jsonb) | ||||
json_strip_nulls(from_json json) | json | 返回from_json,其中所有具有空值的对象域都被省略。其他空值不动。 | select json_strip_nulls('[{"f1":1,"f2":null},2,null,3]') |
[{"f1":1},2,null,3] |
jsonb_strip_nulls(from_json jsonb) | jsonb | |||
jsonb_set(target jsonb, path text[], new_value jsonb[,create_missing boolean]) | jsonb | 返回target,其中由path指定的节用new_value替换,如果path指定的项不存在并且create_missing为真(默认为 true)则加上new_value。正如面向路径的操作符一样,出现在path中的负整数表示从JSON数组的末尾开始数。 | select jsonb_set('[{"f1":1,"f2":null},2,null,3]', '{0,f1}','[2,3,4]', false); |
[{"f1":[2,3,4],"f2":null},2,null,3] |
select jsonb_set('[{"f1":1,"f2":null},2]', '{0,f3}','[2,3,4]') |
[{"f1": 1, "f2": null, "f3": [2, 3, 4]}, 2] |
|||
jsonb_insert(target jsonb, path text[], new_value jsonb, [insert_after boolean]) | jsonb | 返回被插入了new_value的target。如果path指定的target节在一个JSONB数组中,new_value将被插入到目标之前(insert_after为false,默认情况)或者之后(insert_after为真)。如果path指定的target节在一个JSONB对象内,则只有当target不存在时才插入new_value。对于面向路径的操作符来说,出现在path中的负整数表示从JSON数组的末尾开始计数。 | select jsonb_insert('{"a": [0,1,2]}', '{a, 1}', '"new_value"') |
{"a": [0, "new_value", 1, 2]} |
select jsonb_insert('{"a": [0,1,2]}', '{a, 1}', '"new_value"', true) |
{"a": [0, 1, "new_value", 2]} |
|||
jsonb_pretty(from_json jsonb) | text | 把from_json返回成一段缩进后的JSON文本。 | select jsonb_pretty('[{"f1":1,"f2":null},2,null,3]') |
|
jsonb_agg | jsonb | 将值(包括空值)聚合为JSON数组。 |
|
|
jsonb_object_agg | jsonb | 将Key/Value对聚合为JSON对象,值可以为空,但名称不能为空。 |
|
|
is_valid_json | BOOLEAN | IS_VALID_JSON函数用于验证JSON字符串,如果字符串格式是正确的JSON字符串,则该函数返回布尔值true (t);如果字符串格式不正确,函数将返回false (f)。
说明
|
|
|
更多关于JSON类型的用法,请参见JSON函数和操作符。
JSONB索引
从Hologres V1.1版本开始,支持JSONB索引,如下为您介绍在JSONB类型字段上建GIN索引的语法解释和使用示例。
- 语法解释
JSONB类型支持GIN,BTree索引。一般情况下,会在JSONB类型字段上建GIN索引,建GIN索引存在三种方式,语法分别如下。
- 使用默认的jsonb_ops操作符创建索引
CREATE INDEX idx_name ON table_name USING gin (idx_col);
- 使用jsonb_path_ops操作符创建索引
CREATE INDEX idx_name ON table_name USING gin (idx_col jsonb_path_ops);
- 使用jsonb_holo_path_ops操作符创建索引
CREATE INDEX idx_name ON table_name USING gin (idx_col jsonb_holo_path_ops);
- 使用默认的jsonb_ops操作符创建索引
- 使用示例
- 原生PostgreSQL操作符
- 创建jsonb_ops操作符号索引
- 创建表的SQL语句如下。
DROP TABLE IF EXISTS json_table; CREATE TABLE IF NOT EXISTS json_table ( id INT ,j jsonb );
- 创建jsonb_ops操作符号索引的SQL语句如下。
CREATE INDEX index_json on json_table USING GIN(j);
- 在表中插入数据的SQL语句如下。
INSERT INTO json_table VALUES (1, '{"key1": 1, "key2": [1, 2], "key3": {"a": "b"}}') , (1, '{"key1": 1}'), (2, '{"key2": [1, 2], "key3": {"a": "b"}}') ;
- 筛选包含数据的SQL语句如下。
SELECT * FROM json_table WHERE j ? 'key1' ;
- 执行结果如下。
id | j ----+------------------------------------------------- 1 | {"key1": 1, "key2": [1, 2], "key3": {"a": "b"}} 1 | "key1" (2 rows)
- 使用
explain
命令查看执行计划如下。
执行计划中出现了QUERY PLAN ------------------------------------------------------------------------------------------- Gather (cost=0.00..12.36 rows=1 width=66) -> Exchange (Gather Exchange) (cost=0.00..12.36 rows=1 width=66) -> Decode (cost=0.00..12.36 rows=1 width=66) -> Bitmap Heap Scan on json_table (cost=0.00..12.26 rows=1 width=66) Recheck Cond: (j ? 'key1'::text) -> Bitmap Index Scan on index_json (cost=0.00..0.00 rows=0 width=0) Index Cond: (j ? 'key1'::text) Optimizer: HQO version 1.1.0 (8 rows)
Index Scan
步骤,表明查询过程使用了索引。
- 创建表的SQL语句如下。
- 创建jsonb_path_ops操作符号索引
- 创建表的SQL语句如下。
DROP TABLE IF EXISTS json_table; CREATE TABLE IF NOT EXISTS json_table ( id INT ,j jsonb );
- 创建jsonb_path_ops操作符号索引的SQL语句如下。
CREATE INDEX index_json on json_table USING GIN(j jsonb_path_ops);
- 插入数据的SQL语句如下。
INSERT INTO json_table ( SELECT i, ('{ "key1": "'||i||'" ,"key2": "'||i%100||'" ,"key3": "'||i%1000 ||'" ,"key4": "'||i%10000||'" ,"key5": "'||i%100000||'" }')::jsonb FROM generate_series(1, 1000000) i ) ;
- 筛选包含'{"key1": "10"}'数据的SQL语句如下。
SELECT * FROM json_table WHERE j @> '{"key1": "10"}'::JSONB ;
- 执行结果如下。
id | j ----+------------------------------------------------------------------------ 10 | {"key1": "10", "key2": "10", "key3": "10", "key4": "10", "key5": "10"} (1 row)
- 使用
explain
命令查看执行计划如下。
执行计划中出现了QUERY PLAN ------------------------------------------------------------------------------------------- Gather (cost=0.00..0.26 rows=1000 width=12) -> Exchange (Gather Exchange) (cost=0.00..0.23 rows=1000 width=12) -> Decode (cost=0.00..0.23 rows=1000 width=12) -> Bitmap Heap Scan on json_table (cost=0.00..0.13 rows=1000 width=12) Recheck Cond: (j @> '{"key1": "10"}'::jsonb) -> Bitmap Index Scan on index_json (cost=0.00..0.00 rows=0 width=0) Index Cond: (j @> '{"key1": "10"}'::jsonb) Optimizer: HQO version 1.1.0 (8 rows)
Index Scan
步骤,表明查询过程使用了索引。
- 创建表的SQL语句如下。
- 创建jsonb_ops操作符号索引
- Hologres操作符
由于原生PostgreSQL的JSONB的GIN索引是非精确的索引,所以检索数据后需要进行recheck动作。最终导致创建索引后性能不一定提升。针对上述情况,Hologres实现了一种新的ops_class,可以省去recheck的动作,且若不指定索引操作符,系统会默认使用该操作符,具体使用方式如下。
其中jsonb_holo_ops对应jsonb_ops,支持
?, ?|, ?&, @>
的过滤操作。其中jsonb_holo_path_ops对应jsonb_path_ops,仅支持@>
的过滤操作。- 创建jsonb_holo_ops操作符号索引
- 创建表的SQL语句如下。
DROP TABLE IF EXISTS json_table; CREATE TABLE IF NOT EXISTS json_table ( id INT ,j jsonb );
- 创建jsonb_holo_ops操作符号索引的SQL语句如下。
-- 创建索引,使用jsonb_holo_ops操作符 CREATE INDEX index_json on json_table USING GIN(j jsonb_holo_ops);
- 插入数据的SQL语句如下。
INSERT INTO json_table VALUES (1, '{"key1": 1, "key2": [1, 2], "key3": {"a": "b"}}') , (1, '{"key1": 1}'), (2, '{"key2": [1, 2], "key3": {"a": "b"}}') ;
- 筛选包含数据的SQL语句如下。
SELECT * FROM json_table WHERE j ? 'key1' ;
- 执行结果如下。
id | j ----+------------------------------------------------- 1 | {"key1": 1, "key2": [1, 2], "key3": {"a": "b"}} 1 | {"key1": 1} (2 rows)
- 创建表的SQL语句如下。
- 创建jsonb_holo_path_ops操作符号索引
- 创建表的SQL语句如下。
DROP TABLE IF EXISTS json_table; CREATE TABLE IF NOT EXISTS json_table ( id INT ,j jsonb );
- 创建jsonb_holo_path_ops操作符号索引的SQL语句如下。
CREATE INDEX index_json on json_table USING GIN(j jsonb_holo_path_ops);
- 插入数据的SQL语句如下。
INSERT INTO json_table ( SELECT i, ('{ "key1": "'||i||'" ,"key2": "'||i%100||'" ,"key3": "'||i%1000 ||'" ,"key4": "'||i%10000||'" ,"key5": "'||i%100000||'" }')::jsonb FROM generate_series(1, 1000000) i ) ;
- 筛选包含'{"key1": "10"}'数据的SQL语句如下。
SELECT * FROM json_table WHERE j @> '{"key1": "10"}'::JSONB ;
- 执行结果如下。
id | j ----+------------------------------------------------------------------------ 10 | {"key1": "10", "key2": "10", "key3": "10", "key4": "10", "key5": "10"} (1 row)
- 使用
explain
命令查看执行计划如下。
执行计划中出现了QUERY PLAN Gather (cost=0.00..39038928.99 rows=400000 width=88) -> Exchange (Gather Exchange) (cost=0.00..39038843.49 rows=400000 width=88) -> Decode (cost=0.00..39038843.37 rows=400000 width=88) -> Bitmap Heap Scan on json_table (cost=0.00..39038840.00 rows=400000 width=88) " Recheck Cond: (j @> '{"key1": "10"}'::jsonb)" -> Bitmap Index Scan on index_json (cost=0.00..0.00 rows=0 width=0) " Index Cond: (j @> '{"key1": "10"}'::jsonb)" Optimizer: HQO version 0.10.0
Index Scan
步骤,表明查询过程使用了索引。
- 创建表的SQL语句如下。
- 创建jsonb_holo_ops操作符号索引
- 原生PostgreSQL操作符
JSONB列式存储优化
从Hologres V1.3版本开始,支持对于JSONB类型开启列存优化,能够减少JSONB的存储并加速查询。
如下图示例,开启列式存储后底层会自动将Schemaless的Jsonb列,转换为强Schema的列式存储,查询时就可以直接命中查询的列,提升查询性能。
具体使用方法如下。

- 语法解释。
- 对某张表的某个列打开JSONB列存优化。
table_name为表名称;column_name为列名称。-- 打开xx表的xx列的JSONB列式存储优化 ALTER TABLE <table_name> ALTER COLUMN <column_name> SET (enable_columnar_type = ON);
重要 打开JSONB列存优化后,系统在Compaction时将历史数据都转为列存,待Compaction完毕即完成历史数据的列存化。同时新写入的数据会按照列存存储。您可以使用vacuum <table_name>;
命令强制触发Compaction操作,由于Compaction会消耗系统资源,建议在业务低峰期操作。待vacuum
命令执行完毕,Compaction操作就执行完毕。 - 关闭JSONB列存优化。
table_name为表名称;column_name为列名称。-- 关闭xx表的xx列的JSONB列式存储优化 ALTER TABLE <table_name> ALTER COLUMN <column_name> SET (enable_columnar_type = OFF);
重要 关闭JSONB列存优化后,系统在Compaction时将历史数据都转为标准的JSONB存储方式,待Compaction完毕即完成历史数据的转换。同时新写入的数据会按照标准的JSONB存储方式存储。您可以使用vacuum <table_name>;
命令强制触发Compaction操作,由于Compaction会消耗系统资源,建议在业务低峰期操作。待vacuum
命令执行完毕,Compaction操作就执行完毕。 - 查看某张表的配置情况
table_name为表名称。SELECT DISTINCT a.attnum as num, a.attname as name, format_type(a.atttypid, a.atttypmod) as type, a.attnotnull as notnull, com.description as comment, coalesce(i.indisprimary,false) as primary_key, def.adsrc as default, a.attoptions FROM pg_attribute a JOIN pg_class pgc ON pgc.oid = a.attrelid LEFT JOIN pg_index i ON (pgc.oid = i.indrelid AND i.indkey[0] = a.attnum) LEFT JOIN pg_description com on (pgc.oid = com.objoid AND a.attnum = com.objsubid) LEFT JOIN pg_attrdef def ON (a.attrelid = def.adrelid AND a.attnum = def.adnum) WHERE a.attnum > 0 AND pgc.oid = a.attrelid AND pg_table_is_visible(pgc.oid) AND NOT a.attisdropped AND pgc.relname = '<table_name>' -- 表名称 ORDER BY a.attnum;
返回结果可以看到某个列的
attoptions
属性为enable_columnar_type = ON
,表示已经配置成功。
- 对某张表的某个列打开JSONB列存优化。
- 使用示例
- 创建表SQL命令如下。
DROP TABLE IF EXISTS user_tags; -- 创建数据表 BEGIN; CREATE TABLE IF NOT EXISTS user_tags ( ds timestamptz, tags jsonb ); COMMIT;
- 打开JSONB列存优化SQL命令如下。
-- 打开tags列的JSONB列存优化 ALTER TABLE user_tags ALTER COLUMN tags SET (enable_columnar_type = ON);
- 查看是否设置成功
- 查看配置命令如下。
SELECT DISTINCT a.attnum as num, a.attname as name, format_type(a.atttypid, a.atttypmod) as type, a.attnotnull as notnull, com.description as comment, coalesce(i.indisprimary,false) as primary_key, def.adsrc as default, a.attoptions FROM pg_attribute a JOIN pg_class pgc ON pgc.oid = a.attrelid LEFT JOIN pg_index i ON (pgc.oid = i.indrelid AND i.indkey[0] = a.attnum) LEFT JOIN pg_description com on (pgc.oid = com.objoid AND a.attnum = com.objsubid) LEFT JOIN pg_attrdef def ON (a.attrelid = def.adrelid AND a.attnum = def.adnum) WHERE a.attnum > 0 AND pgc.oid = a.attrelid AND pg_table_is_visible(pgc.oid) AND NOT a.attisdropped AND pgc.relname = 'user_tags' -- 表名 ORDER BY a.attnum;
- 结果
可以看到tags行的attoptions属性是
enable_columnar_type = on
,表示已经配置成功。
- 查看配置命令如下。
- 导入数据SQL命令如下。
INSERT INTO user_tags (ds, tags) SELECT '2022-01-01 00:00:00+08' , ('{"id":' || i || ',"first_name" :"Sig", "gender" :"Male"}')::jsonb FROM generate_series(1, 1001) i;
- (可选)强制触发数据落盘。
写入数据后,系统会在数据落盘时进行JSONB的列存优化,为了尽快看到效果,此处使用如下后台命令,强制触发数据落盘。
SELECT hg_admin_command ('flush', 'table_name=user_tags'); VACUUM user_tags;
- 样例查询
使用如下SQL查询id为10的first_name。
SELECT (tags -> 'first_name')::text AS first_name FROM user_tags WHERE (tags -> 'id')::int = 10;
- 查看列存优化是否生效
- 通过如下命令查看执行计划。
-- 显示详细的统计信息 SET hg_experimental_show_execution_statistics_in_explain = ON; -- 查看执行计划 EXPLAIN ANALYZE SELECT (tags -> 'first_name')::text AS first_name FROM user_tags WHERE (tags -> 'id')::int = 10;
- 结果
执行计划如下所示,其中结果中有
columnar_access_used
,表示JSONB列存优化生效。
- 通过如下命令查看执行计划。
- 创建表SQL命令如下。