全部產品
Search
文件中心

Hologres:計算群組執行個體快速入門

更新時間:Jul 12, 2024

Hologres V2.0版本推出了全新的彈性高可用執行個體形態,將計算資源分解為不同的計算群組(Virtual Warehouse),更好的服務於高可用部署。本文為您介紹如何使用計算群組。

背景資訊

在Hologres 1.1版本已經實現了共用儲存的多執行個體讀寫分離的高可用部署架構,一個主執行個體可以綁定多個唯讀從執行個體,執行個體與執行個體之間共用儲存,但是計算資源是互相隔離的,從而實現讀寫分離高可用部署,詳情請參見主從執行個體讀寫分離部署(共用儲存)

但是現在的唯讀從執行個體模式,存在以下限制:

  • 多個執行個體使用獨立的Endpoint,切換流量時,需要更改Endpoint。

  • 唯讀從執行個體和主執行個體共用一套中繼資料,無法根據每個唯讀從執行個體的作用單獨設定參數,例如根據查詢高可用的要求,針對每個唯讀從執行個體設定不一樣的Replica(副本)數。

為瞭解決以上問題,Hologres V2.0版本推出了全新的彈性高可用執行個體形態,將計算資源分解為不同的計算群組(Virtual Warehouse),相較於唯讀從執行個體模式,具備如下優點:

  • 計算群組之間共用資料、中繼資料。

  • 使用一個Endpoint,無需切換Endpoint即可實現流量切換。

計算群組架構介紹請參見計算群組架構介紹

注意事項

僅Hologres V2.0.4及以上版本支援使用計算群組執行個體,如果您的執行個體是V2.0.4以下版本,請您使用自助升級或加入HologresDingTalk交流群反饋,詳情請參見如何擷取更多的線上支援?

使用說明

情境1:建立全新的計算群組執行個體

  • 示意圖

    情境示意圖如下:使用init_warehouse寫入計算群組用於寫入資料;使用read_warehouse_1查詢計算群組用於服務查詢。

    image..png

  • 操作步驟

    1. 建立資料庫。

      1. Superuser帳號登入HoloWeb建立名稱為erp_database的資料庫,詳情請參見建立資料庫image.png

      2. 登入資料庫後,使用如下SQL向其中匯入範例資料。

        DROP FOREIGN TABLE IF EXISTS odps_customer_10g;
        DROP FOREIGN TABLE IF EXISTS odps_lineitem_10g;
        DROP FOREIGN TABLE IF EXISTS odps_nation_10g;
        DROP FOREIGN TABLE IF EXISTS odps_orders_10g;
        DROP FOREIGN TABLE IF EXISTS odps_part_10g;
        DROP FOREIGN TABLE IF EXISTS odps_partsupp_10g;
        DROP FOREIGN TABLE IF EXISTS odps_region_10g;
        DROP FOREIGN TABLE IF EXISTS odps_supplier_10g;
        
        
        IMPORT FOREIGN SCHEMA "MAXCOMPUTE_PUBLIC_DATA#default" LIMIT to
        (
            odps_customer_10g,
            odps_lineitem_10g,
            odps_nation_10g,
            odps_orders_10g,
            odps_part_10g,
            odps_partsupp_10g,
            odps_region_10g,
            odps_supplier_10g
        ) 
        FROM SERVER odps_server INTO public OPTIONS(if_table_exist'error',if_unsupported_type'error');
        
        DROP TABLE IF EXISTS LINEITEM;
        
        BEGIN;
        CREATE TABLE LINEITEM
        (
            L_ORDERKEY      BIGINT      NOT NULL,
            L_PARTKEY       INT         NOT NULL,
            L_SUPPKEY       INT         NOT NULL,
            L_LINENUMBER    INT         NOT NULL,
            L_QUANTITY      DECIMAL(15,2) NOT NULL,
            L_EXTENDEDPRICE DECIMAL(15,2) NOT NULL,
            L_DISCOUNT      DECIMAL(15,2) NOT NULL,
            L_TAX           DECIMAL(15,2) NOT NULL,
            L_RETURNFLAG    TEXT        NOT NULL,
            L_LINESTATUS    TEXT        NOT NULL,
            L_SHIPDATE      TIMESTAMPTZ NOT NULL,
            L_COMMITDATE    TIMESTAMPTZ NOT NULL,
            L_RECEIPTDATE   TIMESTAMPTZ NOT NULL,
            L_SHIPINSTRUCT  TEXT        NOT NULL,
            L_SHIPMODE      TEXT        NOT NULL,
            L_COMMENT       TEXT        NOT NULL,
            PRIMARY KEY (L_ORDERKEY,L_LINENUMBER)
        );
        CALL set_table_property('LINEITEM', 'clustering_key', 'L_SHIPDATE,L_ORDERKEY');
        CALL set_table_property('LINEITEM', 'segment_key', 'L_SHIPDATE');
        CALL set_table_property('LINEITEM', 'distribution_key', 'L_ORDERKEY');
        CALL set_table_property('LINEITEM', 'bitmap_columns', 'L_ORDERKEY,L_PARTKEY,L_SUPPKEY,L_LINENUMBER,L_RETURNFLAG,L_LINESTATUS,L_SHIPINSTRUCT,L_SHIPMODE,L_COMMENT');
        CALL set_table_property('LINEITEM', 'dictionary_encoding_columns', 'L_RETURNFLAG,L_LINESTATUS,L_SHIPINSTRUCT,L_SHIPMODE,L_COMMENT');
        CALL set_table_property('LINEITEM', 'time_to_live_in_seconds', '31536000');
        COMMIT;
        
        DROP TABLE IF EXISTS ORDERS;
        
        BEGIN;
        CREATE TABLE ORDERS
        (
            O_ORDERKEY      BIGINT      NOT NULL PRIMARY KEY,
            O_CUSTKEY       INT         NOT NULL,
            O_ORDERSTATUS   TEXT        NOT NULL,
            O_TOTALPRICE    DECIMAL(15,2) NOT NULL,
            O_ORDERDATE     timestamptz NOT NULL,
            O_ORDERPRIORITY TEXT        NOT NULL,
            O_CLERK         TEXT        NOT NULL,
            O_SHIPPRIORITY  INT         NOT NULL,
            O_COMMENT       TEXT        NOT NULL
        );
        CALL set_table_property('ORDERS', 'segment_key', 'O_ORDERDATE');
        CALL set_table_property('ORDERS', 'distribution_key', 'O_ORDERKEY');
        CALL set_table_property('ORDERS', 'bitmap_columns', 'O_ORDERKEY,O_CUSTKEY,O_ORDERSTATUS,O_ORDERPRIORITY,O_CLERK,O_SHIPPRIORITY,O_COMMENT');
        CALL set_table_property('ORDERS', 'dictionary_encoding_columns', 'O_ORDERSTATUS,O_ORDERPRIORITY,O_CLERK,O_COMMENT');
        CALL set_table_property('ORDERS', 'time_to_live_in_seconds', '31536000');
        COMMIT;
        
        DROP TABLE IF EXISTS PARTSUPP;
        
        BEGIN;
        CREATE TABLE PARTSUPP
        (
            PS_PARTKEY    INT    NOT NULL,
            PS_SUPPKEY    INT    NOT NULL,
            PS_AVAILQTY   INT    NOT NULL,
            PS_SUPPLYCOST DECIMAL(15,2) NOT NULL,
            PS_COMMENT    TEXT   NOT NULL,
            PRIMARY KEY(PS_PARTKEY,PS_SUPPKEY)
        );
        CALL set_table_property('PARTSUPP', 'distribution_key', 'PS_PARTKEY');
        CALL set_table_property('PARTSUPP', 'colocate_with', 'LINEITEM');
        CALL set_table_property('PARTSUPP', 'bitmap_columns', 'PS_PARTKEY,PS_SUPPKEY,PS_AVAILQTY,PS_COMMENT');
        CALL set_table_property('PARTSUPP', 'dictionary_encoding_columns', 'PS_COMMENT');
        CALL set_table_property('PARTSUPP', 'time_to_live_in_seconds', '31536000');
        COMMIT;
        
        DROP TABLE IF EXISTS PART;
        
        BEGIN;
        CREATE TABLE PART
        (
            P_PARTKEY     INT    NOT NULL PRIMARY KEY,
            P_NAME        TEXT   NOT NULL,
            P_MFGR        TEXT   NOT NULL,
            P_BRAND       TEXT   NOT NULL,
            P_TYPE        TEXT   NOT NULL,
            P_SIZE        INT    NOT NULL,
            P_CONTAINER   TEXT   NOT NULL,
            P_RETAILPRICE DECIMAL(15,2) NOT NULL,
            P_COMMENT     TEXT   NOT NULL
        );
        CALL set_table_property('PART', 'distribution_key', 'P_PARTKEY');
        CALL set_table_property('PART', 'bitmap_columns', 'P_PARTKEY,P_SIZE,P_NAME,P_MFGR,P_BRAND,P_TYPE,P_CONTAINER,P_COMMENT');
        CALL set_table_property('PART', 'dictionary_encoding_columns', 'P_NAME,P_MFGR,P_BRAND,P_TYPE,P_CONTAINER,P_COMMENT');
        CALL set_table_property('PART', 'time_to_live_in_seconds', '31536000');
        COMMIT;
        
        
        
        DROP TABLE IF EXISTS CUSTOMER;
        BEGIN;
        CREATE TABLE CUSTOMER
        (
            C_CUSTKEY    INT    NOT NULL PRIMARY KEY,
            C_NAME       TEXT   NOT NULL,
            C_ADDRESS    TEXT   NOT NULL,
            C_NATIONKEY  INT    NOT NULL,
            C_PHONE      TEXT   NOT NULL,
            C_ACCTBAL    DECIMAL(15,2) NOT NULL,
            C_MKTSEGMENT TEXT   NOT NULL,
            C_COMMENT    TEXT   NOT NULL
        );
        CALL set_table_property('CUSTOMER', 'distribution_key', 'C_CUSTKEY');
        CALL set_table_property('CUSTOMER', 'bitmap_columns', 'C_CUSTKEY,C_NATIONKEY,C_NAME,C_ADDRESS,C_PHONE,C_MKTSEGMENT,C_COMMENT');
        CALL set_table_property('CUSTOMER', 'dictionary_encoding_columns', 'C_NAME,C_ADDRESS,C_PHONE,C_MKTSEGMENT,C_COMMENT');
        CALL set_table_property('CUSTOMER', 'time_to_live_in_seconds', '31536000');
        COMMIT;
        
        DROP TABLE IF EXISTS SUPPLIER;
        
        BEGIN;
        CREATE TABLE SUPPLIER
        (
            S_SUPPKEY   INT    NOT NULL PRIMARY KEY,
            S_NAME      TEXT   NOT NULL,
            S_ADDRESS   TEXT   NOT NULL,
            S_NATIONKEY INT    NOT NULL,
            S_PHONE     TEXT   NOT NULL,
            S_ACCTBAL   DECIMAL(15,2) NOT NULL,
            S_COMMENT   TEXT   NOT NULL
        );
        CALL set_table_property('SUPPLIER', 'distribution_key', 'S_SUPPKEY');
        CALL set_table_property('SUPPLIER', 'bitmap_columns', 'S_SUPPKEY,S_NAME,S_ADDRESS,S_NATIONKEY,S_PHONE,S_COMMENT');
        CALL set_table_property('SUPPLIER', 'dictionary_encoding_columns', 'S_NAME,S_ADDRESS,S_PHONE,S_COMMENT');
        CALL set_table_property('SUPPLIER', 'time_to_live_in_seconds', '31536000');
        COMMIT;
        
        DROP TABLE IF EXISTS NATION;
        
        BEGIN;
        CREATE TABLE NATION(
          N_NATIONKEY INT NOT NULL PRIMARY KEY,
          N_NAME text NOT NULL,
          N_REGIONKEY INT NOT NULL,
          N_COMMENT text NOT NULL
        );
        CALL set_table_property('NATION', 'distribution_key', 'N_NATIONKEY');
        CALL set_table_property('NATION', 'bitmap_columns', 'N_NATIONKEY,N_NAME,N_REGIONKEY,N_COMMENT');
        CALL set_table_property('NATION', 'dictionary_encoding_columns', 'N_NAME,N_COMMENT');
        CALL set_table_property('NATION', 'time_to_live_in_seconds', '31536000');
        COMMIT;
        
        DROP TABLE IF EXISTS REGION;
        
        BEGIN;
        CREATE TABLE REGION
        (
            R_REGIONKEY INT  NOT NULL PRIMARY KEY,
            R_NAME      TEXT NOT NULL,
            R_COMMENT   TEXT
        );
        CALL set_table_property('REGION', 'distribution_key', 'R_REGIONKEY');
        CALL set_table_property('REGION', 'bitmap_columns', 'R_REGIONKEY,R_NAME,R_COMMENT');
        CALL set_table_property('REGION', 'dictionary_encoding_columns', 'R_NAME,R_COMMENT');
        CALL set_table_property('REGION', 'time_to_live_in_seconds', '31536000');
        COMMIT;
        
        INSERT INTO public.customer SELECT * FROM public.odps_customer_10g ;
        INSERT INTO public.lineitem SELECT * FROM public.odps_lineitem_10g ;
        INSERT INTO public.nation SELECT * FROM public.odps_nation_10g ;
        INSERT INTO public.orders SELECT * FROM public.odps_orders_10g ;
        INSERT INTO public.part SELECT * FROM public.odps_part_10g ;
        INSERT INTO public.partsupp SELECT * FROM public.odps_partsupp_10g ;
        INSERT INTO public.region SELECT * FROM public.odps_region_10g ;
        INSERT INTO public.supplier SELECT * FROM public.odps_supplier_10g ;
        
        vacuum nation;
        vacuum region;
        vacuum supplier;
        vacuum customer;
        vacuum part;
        vacuum partsupp;
        vacuum orders;
        vacuum lineitem;
        
        analyze nation;
        analyze region;
        analyze lineitem;
        analyze orders;
        analyze customer;
        analyze part;
        analyze partsupp;
        analyze supplier;
        analyze lineitem (l_orderkey,l_partkey,l_suppkey);
        analyze orders (o_custkey);
        analyze partsupp(ps_partkey,ps_suppkey);
    2. 建立計算群組。

      1. Superuser帳號登入HoloWeb,在頂部功能表列選擇資訊安全中心 > 計算群組管理

        您可以在計算群組管理頁面查看執行個體現有的計算群組。

        image.png

      2. 計算群組管理頁面的右上方,單擊新增計算群組

      3. 新增計算群組對話方塊,填寫計算群組名稱和選擇計算群組資源

        本情境新增名稱為read_warehouse_1的計算群組:image.png

      4. 計算群組管理頁面可查看計算群組狀態,待計算群組對應的狀態列為正在運行時,即計算群組建立成功。

        image.png

    3. 向計算群組載入資料。

      Table Group是Hologres中資料的載體。預設情況下,新建立的計算群組無權訪問任何Table Group,所以如果要使用計算群組查詢資料,需要先為計算群組賦予Table Group的許可權。

      1. 查看當前資料庫的Table Group。

        使用如下SQL查看當前資料庫有哪些Table Group:

        SELECT tablegroup_name
        FROM hologres.hg_table_group_properties
        GROUP BY tablegroup_name;

        返回結果樣本如下:image..png

        即當前資料庫僅有一個Table Group。

      2. 為計算群組載入Table Group。

        由於需要使用read_warehouse_1查詢該資料庫中erp_database_tg_default Table Group的資料,所以需要使用如下SQL為計算群組read_warehouse_1載入erp_database_tg_default

        CALL hg_table_group_load_to_warehouse ('erp_database.erp_database_tg_default', 'read_warehouse_1', 1);
      3. 查看計算群組載入Table Group的情況。

        select * from hologres.hg_warehouse_table_groups;

        樣本返回結果如下:image..png

        read_warehouse_1已經載入了erp_database_tg_default 這個Table Group的資料。

    4. 設定使用者權限。

      預設情況下建立的計算群組,非授權使用者不能訪問,當您需要讓其他帳號訪問計算群組時需要進行授權。為ram_testRAM使用者授權訪問read_warehouse_1計算群組授權樣本如下:

      1. 查看使用者擁有計算群組的許可權資訊。

        select * from hologres.hg_warehouse_users;
      2. 查看使用者預設計算群組的資訊。

        select * from hologres.hg_user_default_warehouse;
      3. 在執行個體中加入使用者。

        在HoloWeb的使用者管理頁面添加RAM使用者至Hologres執行個體,詳情請參見使用者管理

        image..png

      4. 賦予ram_test使用者erp_databse資料庫的查詢許可權。

        在HoloWeb的DB授權頁面,為ram_test使用者授予資料庫的查詢許可權,詳情請參見RAM使用者權限授權快速入門image..png

      5. 為使用者ram_test添加read_warehouse_1計算群組的許可權。

        CALL hg_grant_warehouse_access_privilege ('read_warehouse_1', 'p4_2xxxxxxxxxxxxxxx');

        參數說明請參見計算群組授權管理

      6. read_warehouse_1計算群組設定為ram_test使用者的預設計算群組。

        由於需要ram_test使用者串連Hologres使用read_warehouse_1的資源,不使用init_warehouse,實現讀寫分離,那麼就需要使用如下命令將ram_test的預設計算群組設定為read_warehouse_1

        CALL hg_set_user_default_warehouse ('p4_2xxxxxxxxxxxxxxx', 'read_warehouse_1');
      7. 查看當前帳號使用的計算群組。

        此時使用ram_test使用者串連執行個體時,使用如下命令驗證使用的計算群組是否為read_warehouse_1

        select current_warehouse();

情境2:計算群組流量切換

在情境一的基礎上,如果發現計算群組read_warehouse_1有故障,此時需要將帳號ram_test的流量切換到init_warehouse計算群組上。

  • 示意圖。image..png

  • 注意事項

    • 由於切換流量需要重新串連才生效,所以需要保證您串連到Hologres的應用具備重連機制。

    • 串連到Hologres時請使用Hologres自動的路由邏輯,切勿在連接字串中指定使用的計算群組名。

  • 操作步驟

    1. 為使用者ram_test添加init_warehouse計算群組的許可權。

      如果之前未給ram_test添加init_warehouse的許可權,需要使用如下命令為使用者ram_test添加init_warehouse計算群組的許可權,讓ram_test使用者可以使用init_warehouse的資源。

      CALL hg_grant_warehouse_access_privilege ('init_warehouse', 'p4_2xxxxxxxxxxxxxxx');
    2. 將init_warehouse計算群組設定為ram_test使用者的預設計算群組。

      使用如下命令將ram_test使用者的預設計算群組設定為init_warehouse,設定完畢後,使用者和執行個體建立新串連即會使用計算群組init_warehouse的資源。

      CALL hg_set_user_default_warehouse ('p4_2xxxxxxxxxxxxxxx', 'init_warehouse');
    3. 斷開所有使用者非預設計算群組的串連。

      SELECT hg_kill_non_default_warehouse_connections(); 
    4. 重建立立串連後,即會使用新配置的預設計算群組串連到執行個體。