日本熟妇hd丰满老熟妇,中文字幕一区二区三区在线不卡 ,亚洲成片在线观看,免费女同在线一区二区

JSON和JSONB類型

本文將為您介紹Hologres中JSON和JSONB數據類型的語法和使用方法。

JSON和JSONB介紹

近年來隨著移動端應用的普及,應用埋點、用戶標簽計算等場景開始誕生,為了更好地支撐這類場景,越來越多的大數據系統開始使用半結構化格式來存儲此類數據,以獲得更加靈活的開發和處理。常用的半結構化類型為JSON和JSONB,在實際業務中JSON和JSONB的區別如下:

  • JSON儲存的是文本格式的數據,JSONB儲存的是Binary格式的數據。

  • JSON插入速度快,查詢速度慢,原因是處理函數必須在每次執行時重新解析該數據。JSONB插入速度慢,而查詢速度快,原因是JSONB數據被存儲在一種分解好的二進制格式中,因為需要做附加的轉換,它在輸入時要稍慢一些。但是JSONB在查詢數據時快很多,因為不需要重新解析。

  • JSON儲存的數據是對數據的完整拷貝,會保留源數據的空格、重復鍵和順序等,如果一個值中的JSON對象包含同一個鍵超過一次,所有的鍵、值對都會被保留。而JSONB在解析時會刪除掉不必要的空格、重復鍵和數據的順序等,如果在輸入中指定了重復的鍵,只有最后一個值會被保留。

JSON和JSONB兩種JSON數據類型,主要的區別之一是效率,具體說明如下:

  • JSON類型數據存儲輸入文本的精準拷貝,處理函數在每次執行時必須重新解析該數據。由于JSON類型數據存儲的是輸入文本的準確拷貝,因此可能會保留因為語法使用而存在的空格等內容。如果一個值中的JSON對象包含同一個鍵超過一次,所有的鍵值對都會被保留( 處理函數會把最后的值當作有效值)。

  • JSONB類型數據被存儲在一種分解好的二進制格式中,因為需要做附加的轉換,在輸入時要稍慢一些。由于不需要解析,因此在處理時要快很多。JSONB不保留空格、不保留對象鍵的順序并且不保留重復的對象鍵。如果在輸入中指定了重復的鍵,只有最后一個值會被保留。

使用限制

Hologres支持JSON和JSONB兩種JSON數據類型,在使用時需要注意的事項如下:

  • 僅Hologres V0.9及以上版本支持JSON類型,如果您的實例是V0.9以下版本,請您使用自助升級或加入Hologres釘釘交流群反饋,詳情請參見如何獲取更多的在線支持?

  • 僅Hologres V1.1及以上版本支持JSONB類型創建GIN索引。

  • 僅Hologres V1.3及以上版本支持JSONB類型開啟列式存儲,且JSONB的列存優化僅能用于列存表,行存表暫不支持,并且至少1000條數據才會觸發列存優化。

  • 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"}';                                    

JSON和JSONB操作符

常用JSON和JSONB操作符

常用的JSON和JSONB操作符如下表所示:

操作符

右操作數類型

描述

操作示例

執行結果

->

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

額外的JSON和JSONB操作符

除了常用的JSON和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[]

數組字符串中的任何一個鍵或元素字符串是否存在于JSON值中。

select '{"a":1, "b":2, "c":3}'::jsonb ?| array['b', 'c']

true

?&

text[]

是否所有數組字符串都存在于JSON值中。

select '["a", "b"]'::jsonb ?& array['a', 'b']

true

||

jsonb

將兩個JSONB值串接成一個新的JSONB值。

說明

||操作符將其每一個JSON中的操作元素串接起來,但不會遞歸操作。例如:兩個操作數都是具有相同鍵字段名稱的對象,則結果中字段的值將恰好是右側操作數的值。

select '["a", "b"]'::jsonb || '["c", "d"]'::jsonb

["a", "b", "c", "d"]

-

text

根據鍵值從左操作數開始刪除鍵或者值。

select '{"a": "b"}'::jsonb - 'a'

{}

-

text[]

根據鍵值從左操作數開始刪除多個鍵或者值。

select '{"a": "b", "c": "d"}'::jsonb - '{a,c}'::text[]

{}

-

integer

刪除指定位置的數組元素(負值表示倒數)。如果JSON不是數組則拋出一個錯誤。

select '["a", "b"]'::jsonb - 1

["a"]

#-

text[]

刪除具有指定路徑元素(對于JSON數組,負值表示倒數)。

select '["a", {"b":1}]'::jsonb #- '{1,b}'

["a", {}]

JSON和JSONB函數

JSON和JSONB處理函數

如下為可以用于處理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"}}')

json_object_keys
------------------
 f1
 f2

jsonb_object_keys(jsonb)

json_populate_record(base anyelement, from_json json)

anyelement

擴展from_json中的對象成一個行,它的列匹配由base定義的記錄類型。

begin;
create table 
myrowtype( a text, b text, c text);commit;
select * from json_populate_record(null::myrowtype, '{"a": 1, "b": ["2", "a b"], "c": {"d": 4, "e": "a b c"}}')
 a |   b       |      c
---+-----------+-------------
 1 | {2,"a b"} | {"d": 4, "e": "a b c"}

jsonb_populate_record(base anyelement, from_json jsonb)

json_populate_recordset(base anyelement, from_json json)

setof anyelement

擴展from_json中最外的對象數組為一個集合,該集合的列匹配由base定義的記錄類型。

begin;
create table 
myrowtype(a text,b text);
commit;
select * from json_populate_recordset(null::myrowtype, '[{"a":1,"b":2},{"a":3,"b":4}]')
 a | b
---+---
 1 | 2
 3 | 4

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]]')

   value
-----------
 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"]')

 value
-----------
 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]')

[
    {
        "f1": 1,
        "f2": null
    },
    2,
    null,
    3
]

jsonb_agg

jsonb

將值(包括空值)聚合為JSON數組。

DROP TABLE IF EXISTS t;

CREATE TABLE t (
    k int PRIMARY KEY,
    class int NOT NULL,
    v text NOT NULL
);

INSERT INTO t (k, class, v)
SELECT
    (1 + s.v),
    CASE (s.v) < 3
    WHEN TRUE THEN
        1
    ELSE
        2
    END,
    chr(97 + s.v)
FROM
    generate_series(0, 5) AS s (v);

SELECT
    class,
    jsonb_agg(v ORDER BY v DESC) FILTER (WHERE v <> 'b') AS "jsonb_agg",
    jsonb_object_agg(v, k ORDER BY v DESC) FILTER (WHERE v <> 'e') AS "jsonb_object_agg(v, k)"
FROM
    t
GROUP BY
    class;
 class |    jsonb_agg    |  jsonb_object_agg(v, k)
-------+-----------------+--------------------------
     1 | ["c", "a"]      | {"a": 1, "b": 2, "c": 3}
     2 | ["f", "e", "d"] | {"d": 4, "f": 6}

jsonb_object_agg

jsonb

將Key/Value對聚合為JSON對象,值可以為空,但名稱不能為空。

DROP TABLE IF EXISTS t;

CREATE TABLE t (
    k int PRIMARY KEY,
    class int NOT NULL,
    v text NOT NULL
);

INSERT INTO t (k, class, v)
SELECT
    (1 + s.v),
    CASE (s.v) < 3
    WHEN TRUE THEN
        1
    ELSE
        2
    END,
    chr(97 + s.v)
FROM
    generate_series(0, 5) AS s (v);

SELECT
    class,
    jsonb_agg(v ORDER BY v DESC) FILTER (WHERE v <> 'b') AS "jsonb_agg",
    jsonb_object_agg(v, k ORDER BY v DESC) FILTER (WHERE v <> 'e') AS "jsonb_object_agg(v, k)"
FROM
    t
GROUP BY
    class;
 class |    jsonb_agg    |  jsonb_object_agg(v, k)
-------+-----------------+--------------------------
     1 | ["c", "a"]      | {"a": 1, "b": 2, "c": 3}
     2 | ["f", "e", "d"] | {"d": 4, "f": 6}

is_valid_json

BOOLEAN

IS_VALID_JSON函數用于驗證JSON字符串,如果字符串格式是正確的JSON字符串,則該函數返回布爾值true(t);如果字符串格式不正確,函數將返回false (f)。

說明
  • 僅Hologres V1.3.12及以上版本支持此函數。

  • ARRAY類型也算是一種JSON類型,也可以被寫入JSON/JSONB類型的列。

DROP TABLE IF EXISTS test_json;

CREATE TABLE test_json (
    id int,
    json_strings text
);

INSERT INTO test_json
    VALUES (1, '{"a":2}'), (2, '{"a":{"b":{"c":1}}}'), (3, '{"a": [1,2,"b"]}');

INSERT INTO test_json
    VALUES (4, '{{}}'), (5, '{1:"a"}'), (6, '[1,2,3]');

SELECT
    id,
    json_strings,
    is_valid_json (json_strings)
FROM
    test_json
ORDER BY
    id;
id | json_strings        | is_valid_json
---+---------------------+--------------
 0 | {"a":2}             | true
 2 | {"a":{"b":{"c":1}}} | true
 4 | {"a": [1,2,"b"]}    | true
 6 | {{}}                | false
 8 | {1:"a"}             | false
10 | [1,2,3]             | true

解析函數

函數

描述

操作示例

執行結果

try_cast_to_jsonb(text)

將TEXT類型轉換為JSONB類型。如果文本字段不符合JSONB格式,將返回NULL值。

說明

僅Hologres V2.0.24及以上版本支持該函數。

  • select try_cast_to_jsonb('{"key": 1}');

  • select try_cast_to_jsonb('{"key": 1');

  • {"key": 1}

  • NULL

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[])

JSONB索引

從Hologres V1.1版本開始,在查詢層支持JSONB類型的GIN, BTree索引加速查詢。在JSONB上創建GIN索引的方式有兩種:使用默認的jsonb_ops操作符創建和使用jsonb_path_ops操作符創建。

說明

當前索引都是針對JSONB類型,請盡量使用JSONB類型而不是JSON類型。

  • 使用默認的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_ops的GIN索引中,JSONB數據中的每個key和value都是作為一個單獨的索引項的,而jsonb_path_ops則只為每個value創建一個索引項。

GIN索引可以通過原生PostgreSQL操作符和Hologres操作符實現,使用示例如下。

原生PostgreSQL操作符

  • 創建jsonb_ops操作符索引。

    --1、創建表
    BEGIN;
    DROP TABLE IF EXISTS json_table;
    
    CREATE TABLE IF NOT EXISTS json_table
    (
        id INT
        ,j jsonb
    );
    COMMIT;
    
    --2、創建jsonb_ops操作符索引
    CREATE INDEX index_json on json_table USING GIN(j);
    
    --3、插入數據
    INSERT INTO json_table VALUES
    (1, '{"key1": 1, "key2": [1, 2], "key3": {"a": "b"}}') ,
    (1, '{"key1": 1}'),
    (2, '{"key2": [1, 2], "key3": {"a": "b"}}') ;
    
    --4、查詢數據
    SELECT  * FROM    json_table WHERE   j ? 'key1';
    --返回結果
     id |                        j
    ----+-------------------------------------------------
      1 | {"key1": 1, "key2": [1, 2], "key3": {"a": "b"}}
      1 | {"key1": 1}
    
                        

    使用explain命令查看執行計劃如下。

    explain SELECT  * FROM    json_table WHERE   j ? 'key1';
    
    QUERY PLAN
    Gather  (cost=0.00..0.26 rows=1000 width=12)
      ->  Local Gather  (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'::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.3.0

    執行計劃中出現了Index Scan步驟,表明查詢過程使用了索引。

  • 創建jsonb_path_ops操作符索引。

    --1、創建表
    BEGIN;
    DROP TABLE IF EXISTS json_table;
    
    CREATE TABLE IF NOT EXISTS json_table
    (
        id INT
        ,j jsonb
    );
    COMMIT;
    
    --2、創建jsonb_ops操作符索引
    CREATE INDEX index_json on json_table USING GIN(j jsonb_path_ops);
    
    --3、插入數據
    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
    ) ;
    
    --4、查詢包含'{"key1": "10"}'的數據
    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命令查看執行計劃如下。

    explain SELECT  * FROM    json_table WHERE   j @> '{"key1": "10"}'::JSONB;
    
                                            QUERY PLAN
    -------------------------------------------------------------------------------------------
     Gather  (cost=0.00..0.26 rows=1000 width=12)
       ->  Local Gather  (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.3.0
    (8 rows)
                        

    執行計劃中出現了Index Scan步驟,表明查詢過程使用了索引。

Hologres操作符

由于原生PostgreSQL的JSONB的GIN索引是非精確的索引,所以檢索數據后需要進行recheck動作。最終導致創建索引后性能不一定提升。針對上述情況,Hologres實現了一種新的ops_class,可以省去recheck的動作,且若不指定索引操作符,系統會默認使用該操作符,具體使用方式如下。

說明

使用該操作符時,由于最大存儲127個字節,超過該長度的索引會被截斷,所以JSONB字段超長時還是會被截斷,從而發生recheck的操作。是否有recheck行為,可以使用EXPLAIN ANALYZE語句查看物理執行計劃驗證。

其中jsonb_holo_ops對應jsonb_ops,支持?, ?|, ?&, @>的過濾操作。其中jsonb_holo_path_ops對應jsonb_path_ops,僅支持@>的過濾操作。

  • 創建jsonb_holo_ops操作符號索引。

    --1、創建表
    BEGIN ;
    DROP TABLE IF EXISTS json_table;
    CREATE TABLE IF NOT EXISTS json_table
    (
        id INT
        ,j jsonb
    );
    COMMIT ;
    
    --2、創建索引,使用jsonb_holo_ops操作符
    CREATE INDEX index_json on json_table USING GIN(j jsonb_holo_ops);
    
    --3、插入數據
    INSERT INTO json_table VALUES
    (1, '{"key1": 1, "key2": [1, 2], "key3": {"a": "b"}}') ,
    (1, '{"key1": 1}'),
    (2, '{"key2": [1, 2], "key3": {"a": "b"}}') ;
    
    --4、查詢
    SELECT  * FROM    json_table WHERE   j ? 'key1';
    --返回結果
     id |                        j
    ----+-------------------------------------------------
      1 | {"key1": 1}
      1 | {"key1": 1, "key2": [1, 2], "key3": {"a": "b"}}
    (2 rows)
  • 創建jsonb_holo_path_ops操作符號索引。

    --1、創建表
    BEGIN ;
    DROP TABLE IF EXISTS json_table;
    CREATE TABLE IF NOT EXISTS json_table
    (
        id INT
        ,j jsonb
    );
    
    --2、創建索引,使用jsonb_holo_path_ops操作符
    CREATE INDEX index_json on json_table USING GIN(j jsonb_holo_path_ops);
    
    --3、插入數據
    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
    ) ;
    
    --4、查詢,篩選包含'{"key1": "10"}'的數據
    SELECT  * FROM  json_table WHERE j @> '{"key1": "10"}'::JSONB ;
    --返回結果
     id |                                   j
    ----+------------------------------------------------------------------------
     10 | {"key1": "10", "key2": "10", "key3": "10", "key4": "10", "key5": "10"}
    (1 row)

數據導入示例:通過Flink實時導入JSONB數據

通過Flink將數據導入Hologres時,在Flink的SQL作業中,需要將字段定義為Flink的數據類型;只有在Hologres中創建內部表時,才需要將字段定義為Hologres的數據類型,Flink與Hologres數據類型映射請參見Blink/Flink與Hologres的數據類型映射。

如果您期望使用Flink將JSON數據寫入Hologres,則需要在Flink SQL作業中,將源表、結果表中的JSON數據字段定義為VARCHAR類型,僅在Hologres內部表中將其定義為JSONB類型,示例如下:

  • Hologres中創建內部表,將message字段定義為JSONB類型:

    BEGIN ;
    DROP TABLE IF EXISTS holo_internal_table;
    CREATE TABLE IF NOT EXISTS holo_internal_table
    (
        id BIGINT NOT NULL,
        message JSONB NOT NULL
    );
    CALL set_table_property('holo_internal_table', 'distribution_key', 'id');
    COMMIT ;
  • Flink作業中將源表、結果表的message字段定義為VARCHAR類型,并寫入Hologres:

    CREATE TEMPORARY TABLE randomSource (
        id BIGINT,
        message VARCHAR
      )
    WITH ('connector' = 'datagen');
    
    CREATE TEMPORARY TABLE sink_holo (
        id BIGINT,
        message VARCHAR
      )
    WITH (
         'connector' = 'hologres',
        'dbname'='<yourDBname>',  --Hologres的數據庫名稱。
        'tablename'='<holo_internal_table>',  --Hologres用于接收數據的表名稱。
        'username'='<yourUsername>',  --當前阿里云賬號的AccessKey ID。
        'password'='<yourPassword>',  --當前阿里云賬號的AccessKey Secret。
        'endpoint'='<yourEndpoint>',  --當前Hologres實例VPC網絡的Endpoint。
      );
    
    INSERT INTO sink_holo
    SELECT 
      1,
      '{"k":"v"}'
    FROM
      randomSource;

高級調優:列式JSONB存儲

GIN索引只是計算層的優化,實際計算時還需要掃描整個JSON內容。為了提升JSONB數據的查詢效率,Hologres從 V1.3版本開始支持JSONB數據的列式存儲,通過存儲層的優化,使得JSONB數據能夠像結構化數據一樣按列式存儲,有效提高數據的壓縮效率,同時也提升JSONB數據的查詢效率。

JSONB列式存儲詳情請參見列式JSONB。