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

列式JSONB

為了提升JSONB數(shù)據(jù)的查詢效率,Hologres從 V1.3版本開始支持對于JSONB類型開啟列式存儲優(yōu)化,能夠降低JSONB數(shù)據(jù)的存儲大小并加速查詢。本文將會為您介紹Hologres中列式JSONB的使用。

列式JSONB原理介紹

如下圖所示開啟JSONB列式存儲優(yōu)化后,系統(tǒng)會在底層自動將JSONB的列轉換為強Schema的列式存儲,查詢JSONB中某一個Value時就可以直接命中指定列,從而提升查詢性能。同時因為JSONB中的Value是按列式存儲的,在存儲層可以達到像普通結構化數(shù)據(jù)一樣的存儲和壓縮效率,從而有效降低存儲,實現(xiàn)降本增效。

說明

JSONB列式存儲優(yōu)化功能對JSON類型數(shù)據(jù)不適用,實際使用過程中請不要對JSON類型開啟列式存儲優(yōu)化。

image

使用限制

  • 僅Hologres V1.3及以上版本支持JSONB類型開啟列式存儲,建議將Hologres實例版本升級至1.3.37及以上版本再開始使用列式JSONB功能,會獲取更好的性能和更優(yōu)的體驗。升級請使用自助升級或加入實時數(shù)倉Hologres交流群申請升級實例,詳情請參見如何獲取更多的在線支持?

  • JSONB的列存優(yōu)化僅能用于列存表,行存表暫不支持,并且至少1000條數(shù)據(jù)才會觸發(fā)列存優(yōu)化。

  • 當前僅支持如下操作符的列式存儲優(yōu)化,并且如果查詢中使用不支持的操作符,反而可能會導致查詢性能下降。

    操作符

    右操作數(shù)據(jù)類型

    描述

    操作與結果

    ->

    text

    通過鍵獲得JSON對象域。

    • 操作示例:

      select '{"a": {"b":"foo"}}'::json->'a'

    • 返回結果:

      {"b":"foo"}

    ->>

    text

    以TEXT形式獲得JSON對象域。

    • 操作示例:

      select '{"a":1,"b":2}'::json->>'b'
    • 返回結果:

      2

列式JSONB使用

開啟列式JSONB

通過以下語句對某張表的某個JSONB列打開JSONB列存優(yōu)化。

-- 打開xx表的xx列的JSONB列式存儲優(yōu)化
ALTER TABLE <table_name> ALTER COLUMN <column_name> SET (enable_columnar_type = ON);

table_name為表名稱;column_name為列名稱。

重要
  • 打開JSONB列存優(yōu)化后,系統(tǒng)在Compaction時將歷史數(shù)據(jù)都轉為列存,待Compaction完畢即完成歷史數(shù)據(jù)的列存化。

  • Compaction會消耗系統(tǒng)資源(比如內存),建議該操作在業(yè)務低峰期操作。可以使用vacuum table_name;命令強制觸發(fā)Compaction操作,待vacuum命令執(zhí)行完畢,Compaction操作就執(zhí)行完畢了。

  • Compaction完成后新寫入的數(shù)據(jù)會按照列存存儲。

開啟Decimal類型推導

重要

開啟Decimal類型推導前,請確保已開啟JSONB列存優(yōu)化。

Hologres從 V2.0.11版本開始,支持將DECIMAL類型的數(shù)據(jù)進行列存優(yōu)化。例如如下的JSON數(shù)據(jù):

{
  "name":"Mike",
  "statistical_period":"2023-01-01 00:00:00+08",
  "balance":123.45
}

balance的數(shù)據(jù)在開啟Decimal推導后,也支持按照列存優(yōu)化。開啟方法如下:

-- 打開xx表的xx列的Decimal列存優(yōu)化
ALTER TABLE <table_name> ALTER COLUMN <column_name> SET (enable_decimal = ON);

table_name為表名稱;column_name為列名稱。

查看某張表的列式JSONB開啟情況

通過以下語句查看某張表的列式JSONB開啟情況。

  • Hologres V1.3.37及以上版本支持如下命令。

    說明

    該命令在Hologres V2.0.17及以下版本只支持看publicSchema下的表,從2.0.18版本開始支持查看其他Schema下的表開啟情況。

    --2.0.17及以下版本僅支持查看public schema的表,2.0.18版本可以查詢其他schema的表
    SELECT * FROM hologres.hg_column_options WHERE schema_name='<schema_name>' AND table_name = '<table_name>';

    其中schema_name為Schema名稱,table_name為表名稱。

  • Hologres V1.3.10~V1.1.36版本使用如下命令。

    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;

    其中table_name為表名稱。

  • 示例返回結果。

    返回結果可以看到某個列的attoptionsoption屬性為enable_columnar_type = ON,則表示已經(jīng)配置成功。

    image

關閉列式JSONB

通過以下命令關閉某張表的某個列的JSONB列存優(yōu)化。

-- 關閉xx表的xx列的JSONB列式存儲優(yōu)化
ALTER TABLE <table_name> ALTER COLUMN <column_name> SET (enable_columnar_type = OFF);

table_name為表名稱;column_name為列名稱。

重要
  • 關閉JSONB列存優(yōu)化后,系統(tǒng)在Compaction時將歷史數(shù)據(jù)都轉為標準的JSONB存儲方式,待Compaction完畢即完成歷史數(shù)據(jù)的轉換。

  • Compaction會消耗系統(tǒng)資源(比如內存),建議該操作在業(yè)務低峰期操作。可以使用vacuum table_name;命令強制觸發(fā)Compaction操作,待vacuum命令執(zhí)行完畢,Compaction操作就執(zhí)行完畢了。

  • Compaction完成后,新寫入的數(shù)據(jù)會按照JSONB格式存儲。

關閉Decimal類型推導

通過以下命令關閉某張表的某個列的Decimal類型列存優(yōu)化推導。

-- 關閉xx表的xx列的Decimal列存優(yōu)化
ALTER TABLE <table_name> ALTER COLUMN <column_name> SET (enable_decimal = OFF);

table_name為表名稱;column_name為列名稱。

說明

Decimal類型推導關閉后,會立刻觸發(fā)Compaction,將原來已經(jīng)列存優(yōu)化后的Decimal類型的數(shù)據(jù)轉換為原有模式。

設置Bitmap索引

在Hologres中,bitmap_columns屬性指定位圖索引,是數(shù)據(jù)存儲之外的獨立索引結構,以位圖向量結構加速等值比較場景,能夠對文件塊內的數(shù)據(jù)進行快速的等值過濾,適用于等值過濾查詢的場景。Hologres從V2.0版本開始支持對開啟了列存的JSONB設置Bitmap索引。開啟列存JSONB后,系統(tǒng)會解析出int、int[]、bigint、bigint[]、text、text[]、jsonb這7種數(shù)據(jù)類型。開啟Bitmap索引后,系統(tǒng)會對推導成int、int[]、bigint、bigint[]、text、text[]類型的數(shù)據(jù)建立Bitmap索引。

使用語法如下:

call set_table_property('<table_name>', 'bitmap_columns', '[<columnName>{:[on|off]}[,...]]');

參數(shù)說明:

參數(shù)

說明

table_name

表名稱。

columnName

列名稱。

on

當前字段打開位圖索引。

重要

僅支持開啟了列存的JSONB設置Bitmap索引。

off

當前字段關閉位圖索引。

使用示例

  1. 創(chuàng)建表。

    DROP TABLE IF EXISTS user_tags;
    
    -- 創(chuàng)建數(shù)據(jù)表
    BEGIN;
    CREATE TABLE IF NOT EXISTS user_tags (
        ds timestamptz,
        tags jsonb
    );
    COMMIT;
  2. 打開tags列的JSONB列存優(yōu)化。

    ALTER TABLE user_tags ALTER COLUMN tags SET (enable_columnar_type = ON);
  3. 查看JSONB列式存儲開啟情況。

    select * from hologres.hg_column_options where table_name = 'user_tags';

    如下返回結果中可以看到tags行的options屬性是enable_columnar_type = on,表示已經(jīng)配置成功。

     schema_name | table_name | column_id | column_name |       column_type        | notnull | comment | default |          options
    -------------+------------+-----------+-------------+--------------------------+---------+---------+---------+---------------------------
     public      | user_tags  |         1 | ds          | timestamp with time zone | f       |         |         |
     public      | user_tags  |         2 | tags        | jsonb                    | f       |         |         | {enable_columnar_type=on}
    (2 rows)
  4. 導入數(shù)據(jù)。

    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, 10001) i;
  5. (可選)強制觸發(fā)數(shù)據(jù)落盤。

    寫入數(shù)據(jù)后,系統(tǒng)會在數(shù)據(jù)落盤時進行JSONB的列存優(yōu)化,為了盡快看到效果,此處使用如下后臺命令,強制觸發(fā)數(shù)據(jù)落盤。

    VACUUM user_tags;
  6. 樣例查詢。

    使用如下SQL查詢id10first_name

    SELECT
        (tags -> 'first_name')::text AS first_name
    FROM
        user_tags
    WHERE (tags -> 'id')::int = 10;
  7. 通過執(zhí)行計劃檢查列存優(yōu)化是否使用。

    -- 顯示詳細的統(tǒng)計信息
    SET hg_experimental_show_execution_statistics_in_explain = ON;
    -- 查看執(zhí)行計劃
    EXPLAIN ANALYZE
    SELECT
        (tags -> 'first_name')::text AS first_name
    FROM
        user_tags
    WHERE (tags -> 'id')::int = 10;

    結果中有columnar_access_used,表示JSONB使用了列存優(yōu)化。

    image

  8. 針對步驟6中的查詢,還可以對tags設置Bitmap索引,以提升針對某個key等值查詢的效率,設置方法如下。

    call set_table_property('user_tags', 'bitmap_columns', 'tags');
  9. 通過執(zhí)行計劃檢查Bitmap索引是否生效。

    -- 查看執(zhí)行計劃
    EXPLAIN ANALYZE
    SELECT
        (tags -> 'first_name')::text AS first_name
    FROM
        user_tags
    WHERE (tags -> 'id')::int = 10;

    返回結果如下:image..png

    結果中有bitmap_used,表示使用了Bitmap索引。

列式JSONB不推薦的使用場景

使用列式JSONB不僅會降低存儲,還會顯著提升查詢效率。但是列式JSONB并不是所有場景都適用,以下場景不建議使用,否則會事倍功半。

查詢會帶出完整JSONB列

Hologres的列式JSONB方案對于大部分使用場景都有比較好的優(yōu)化效果,需要注意的是:對于查詢結果需要帶出完整JSONB列的場景,性能相較于直接存儲原始格式的JSONB會有降低,比如以下SQL:

--建表DDL
CREATE TABLE TBL(key int, json_data jsonb); 
SELECT json_data FROM TBL WHERE key = 123;
SELECT * FROM TBL limit 10;

原因在于底層已經(jīng)將JSONB數(shù)據(jù)轉成了列式存儲,所以當需要查詢出完整JSON數(shù)據(jù)的時候,就需要將那些已經(jīng)列式存儲的數(shù)據(jù)再重新拼裝成原來的JSONB格式:

image

這個步驟就會產生大量的IO以及轉換開銷,如果涉及到的數(shù)據(jù)量很大,列數(shù)又很多,甚至可能成為性能瓶頸,所以此場景下建議不要開啟列式優(yōu)化。

極稀疏的JSONB數(shù)據(jù)

當Hologres列式化JSONB數(shù)據(jù)遇到稀疏的字段時,Hologres會將這部分字段合并至一個叫做holo.remaining的特殊列中,以此來避免列數(shù)膨脹的問題。所以如果JSONB數(shù)據(jù)包含的都是稀疏字段,比如極端情況下每個字段都只會出現(xiàn)一次,那么列式化將不會起效,因為所有字段都是稀疏的,那么所有字段都會合并至holo.remaining字段,等于沒有進行列式化,這種情況下不會有查詢性能的提升。

包含復雜嵌套結構的JSONB數(shù)據(jù)

如下JSONB數(shù)據(jù)的根節(jié)點就是一個數(shù)組,且該數(shù)組中存放的是非同構的JSONB數(shù)據(jù),當前Hologres在列式化JSONB數(shù)據(jù)的時候,遇到類似復雜的嵌套結構,會將這部分數(shù)據(jù)退化成一列,所以此JSONB數(shù)據(jù)開啟列式JSONB優(yōu)化,將不會帶來明顯的查詢性能收益。

'[
  {"key1": "value1"}, 
  {"key2": 123},
  {"key3": 123.01}
]'

列式JSONB最佳實踐

慢查詢診斷

如果開啟列式JSONB后,發(fā)現(xiàn)查詢性能反而比不開啟性能還要差很多,首先排查查詢是否帶出了完整JSONB列,如果SQL過于復雜,可以使用Explain Analyze方式來診斷,SQL命令示例如下:

CREATE TABLE TBL(key int, json_data json); --建表DDL
ALTER TABLE TBL ALTER COLUMN json_data SET (enable_columnar_type = on);
Explain Analyze SELECT json_data FROM TBL WHERE key = 123;

Explain Analyze的結果中會有Hint的信息,如果在Hint信息中有以下內容則代表查詢帶出了完整的JSONB列,導致了性能的退化:

Column 'json_data' has enabled columnar jsonb, but the query scanned the entire Jsonb value

更優(yōu)的SQL寫法

  • 將JSONB字段數(shù)據(jù)轉成TEXT格式有不同的寫法,但是使用->>操作符的性能會更好,比如要獲取json_data列中的name屬性:

    --性能更好
    SELECT json_data->>'name' FROM tbl; 
    --性能一般
    SELECT (json_data->'name')::text FROM tbl;
  • 如果JSON的某個字段中存儲的是TEXT數(shù)組,需要判斷數(shù)組中是否包含特定值,建議使用以下寫法:

    SELECT key FROM tbl WHERE jsonb_to_textarray(json_data->'phones') && ARRAY['123456'];

常見問題

開啟列存化后為什么存儲上漲?

開啟列式JSONB優(yōu)化后,原JSONB數(shù)據(jù)中的字段名都不會再存儲了,而只需存儲每個字段對應的具體值,且列式化后每列的數(shù)據(jù)類型都是一樣的,列式存儲能有比較好的數(shù)據(jù)壓縮率,理論上數(shù)據(jù)的存儲空間會有明顯的下降。

但如果JSONB數(shù)據(jù)中的字段比較稀疏,列數(shù)膨脹比較厲害,那么列式化后的每一列都會帶來額外的存儲開銷(列的統(tǒng)計信息、索引等),且如果列式化后每一列的類型都是TEXT類型,壓縮效果就不會很好。所以實際的存儲壓縮效率與實際業(yè)務的數(shù)據(jù)有關(比如稀疏度等),不一定所有的數(shù)據(jù)都有很好的壓縮效果。