计算组实例快速入门

Hologres V2.0版本推出全新的弹性高可用实例形态,将计算资源分解为不同的计算组(Virtual Warehouse),更好地服务于高可用部署。本文为您介绍如何使用计算组。

背景信息

Hologres V2.0版本推出了全新的计算组实例形态,将计算资源分解为不同的计算组(Virtual Warehouse),能够同时有效支持读写分离、资源隔离及业务隔离等多种场景,为用户提供资源隔离和弹性等核心能力。关于计算组架构介绍详情,请参见计算组架构介绍

注意事项

Hologres V2.0.4及以上版本支持使用计算组实例,如果您的实例是V2.0.4以下版本,请您使用常见升级准备失败报错或加入Hologres钉钉交流群反馈,详情请参见如何获取更多的在线支持?

创建新计算组实例

本节演示新创建read_warehouse_1计算组,实现读写分离,即使用init_warehouse写入计算组用于写入数据,使用read_warehouse_1查询计算组用于服务查询。

image..png

创建数据库

  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);

创建计算组

  1. 登录Hologres管控台,进入目标实例的详情页。

  2. 单击左侧计算组管理,进入计算组资源管理页签。您可以在该页签下查看现有计算组列表。

    jisuan1

  3. 单击新增计算组,进入新增计算组对话框,并填写计算组名称和选择计算组资源

    本场景新增名称为read_warehouse_1的计算组:

    w1

  4. 单击确认完成创建。

  5. 计算组管理页面可查看计算组状态,待计算组对应的状态列为正在运行时,即计算组创建成功。

    e33

向计算组加载数据

Table GroupHologres中数据的载体。默认情况下,新创建的计算组无权访问任何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的数据。

设置用户权限

默认情况下新建的计算组,非授权用户不能访问,当您需要让其他账号访问计算组时需要进行授权。为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数据库的查询权限。

    HoloWebDB授权页面,为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();

计算组流量切换

当您创建完新计算组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. 重新建立连接后,即会使用新配置的默认计算组连接到实例。