Help Center/ Data Warehouse Service/ Best Practices/ Data Analytics/ Using DWS to Analyze the Supply Chain Requirements of a Company
Updated on 2026-07-10 GMT+08:00

Using DWS to Analyze the Supply Chain Requirements of a Company

This practice describes how to load the sample data set from OBS to a data warehouse cluster and perform data queries. This example comprises multi-table analysis and theme analysis in the data analysis scenario.

In this example, a standard TPC-H-1x data set of 1 GB size has been generated on DWS, and has been uploaded to the tpch folder of an OBS bucket. All Huawei Cloud accounts have been granted the read-only permission to access the OBS bucket. Users can easily import the data set using their accounts.

General Procedure

This practice takes about 60 minutes. The process is as follows:

  1. Making Preparations
  2. Step 1: Importing Sample Data
  3. Step 2: Performing Multi-Table Analysis and Theme Analysis

Supported Regions

Table 1 describes the regions where OBS data has been uploaded.

Table 1 Regions and OBS bucket names

Region

OBS Bucket

CN North-Beijing1

dws-demo-cn-north-1

CN North-Beijing2

dws-demo-cn-north-2

CN North-Beijing4

dws-demo-cn-north-4

CN North-Ulanqab1

dws-demo-cn-north-9

CN East-Shanghai1

dws-demo-cn-east-3

CN East-Shanghai2

dws-demo-cn-east-2

CN South-Guangzhou

dws-demo-cn-south-1

CN South-Guangzhou-InvitationOnly

dws-demo-cn-south-4

CN-Hong Kong

dws-demo-ap-southeast-1

AP-Singapore

dws-demo-ap-southeast-3

AP-Bangkok

dws-demo-ap-southeast-2

LA-Santiago

dws-demo-la-south-2

AF-Johannesburg

dws-demo-af-south-1

LA-Mexico City1

dws-demo-na-mexico-1

LA-Mexico City2

dws-demo-la-north-2

RU-Moscow2

dws-demo-ru-northwest-2

LA-Sao Paulo1

dws-demo-sa-brazil-1

Scenario Description

Understand the basic functions of DWS and how to import data. Analyze the order data of a company and its suppliers as follows:

  1. Analyze the revenue brought by suppliers in a region to the company. The statistics can be used to determine whether a local allocation center needs to be established in a given region.
  2. Analyze the relationship between parts and suppliers to obtain the number of suppliers for parts based on the specified contribution conditions. The information can be used to determine whether suppliers are sufficient for large order quantities when the task is urgent.
  3. Analyze the revenue loss of small orders. You can query the average annual revenue loss if there are no small orders. Filter out small orders that are lower than 20% of the average supply volume, and calculate the total amount of those small orders to figure out the average annual revenue loss.
  4. In this practice, the TPC-H sample data consists of eight database tables whose associations are shown in Figure 1.
    Figure 1 TPC-H data tables

Making Preparations

  • You have registered a DWS account and checked the account status before using DWS. The account cannot be in arrears or frozen.
  • Obtain the AK/SK of the account by referring to Creating an Access Key.
  • Create a cluster by referring to Creating a Cluster.

Step 1: Importing Sample Data

After connecting to the cluster using the SQL client tool, perform the following operations in the SQL client tool to import the TPC-H sample data and perform data queries.

  1. In service commissioning, you are advised to use the SQL Editor to connect to the cluster. For details, see Using the SQL Editor to Connect to a Cluster.

    You can also use other methods (such as the command-line tool gsql) to connect to the cluster. For details, see Connecting to a DWS Cluster.

  2. Run the following statement in the editing window to create a table:

      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    DROP TABLE if exists region;
    CREATE TABLE region
    (
            R_REGIONKEY  INT NOT NULL , 
            R_NAME       CHAR(25) NOT NULL ,
            R_COMMENT    VARCHAR(152)
    )
    with (orientation = column, COMPRESSION=MIDDLE)
    distribute by replication;
    
    DROP TABLE if exists nation;
    CREATE TABLE nation
    (
            N_NATIONKEY  INT NOT NULL, 
            N_NAME       CHAR(25) NOT NULL,
            N_REGIONKEY  INT NOT NULL,
            N_COMMENT    VARCHAR(152)
    )
    with (orientation = column,COMPRESSION=MIDDLE)
    distribute by replication;
    
    DROP TABLE if exists supplier;
    CREATE TABLE supplier
    (
            S_SUPPKEY     BIGINT NOT NULL,
            S_NAME        CHAR(25) NOT NULL,
            S_ADDRESS     VARCHAR(40) NOT NULL,
            S_NATIONKEY   INT NOT NULL,
            S_PHONE       CHAR(15) NOT NULL,
            S_ACCTBAL     DECIMAL(15,2) NOT NULL,
            S_COMMENT     VARCHAR(101) NOT NULL
    )
    with (orientation = column,COMPRESSION=MIDDLE)
    distribute by hash(S_SUPPKEY);
    
    DROP TABLE if exists customer;
    CREATE TABLE customer
    (
            C_CUSTKEY     BIGINT NOT NULL,
            C_NAME        VARCHAR(25) NOT NULL,
            C_ADDRESS     VARCHAR(40) NOT NULL, 
            C_NATIONKEY   INT NOT NULL, 
            C_PHONE       CHAR(15) NOT NULL, 
            C_ACCTBAL     DECIMAL(15,2)   NOT NULL,
            C_MKTSEGMENT  CHAR(10) NOT NULL, 
            C_COMMENT     VARCHAR(117) NOT NULL
    )
    with (orientation = column,COMPRESSION=MIDDLE)
    distribute by hash(C_CUSTKEY);
    
    DROP TABLE if exists part;
    CREATE TABLE part
    (
            P_PARTKEY     BIGINT NOT NULL, 
            P_NAME        VARCHAR(55) NOT NULL, 
            P_MFGR        CHAR(25) NOT NULL, 
            P_BRAND       CHAR(10) NOT NULL, 
            P_TYPE        VARCHAR(25) NOT NULL,
            P_SIZE        BIGINT NOT NULL,
            P_CONTAINER   CHAR(10) NOT NULL,
            P_RETAILPRICE DECIMAL(15,2) NOT NULL,
            P_COMMENT     VARCHAR(23) NOT NULL
    )
    with (orientation = column,COMPRESSION=MIDDLE)
    distribute by hash(P_PARTKEY);
    
    DROP TABLE if exists partsupp;
    CREATE TABLE partsupp
    (
            PS_PARTKEY     BIGINT NOT NULL,
            PS_SUPPKEY     BIGINT NOT NULL, 
            PS_AVAILQTY    BIGINT NOT NULL,
            PS_SUPPLYCOST  DECIMAL(15,2)  NOT NULL, 
            PS_COMMENT     VARCHAR(199) NOT NULL
    )
    with (orientation = column,COMPRESSION=MIDDLE)
    distribute by hash(PS_PARTKEY);
    
    DROP TABLE if exists orders;
    CREATE TABLE orders
    (
            O_ORDERKEY       BIGINT NOT NULL,
            O_CUSTKEY        BIGINT NOT NULL, 
            O_ORDERSTATUS    CHAR(1) NOT NULL, 
            O_TOTALPRICE     DECIMAL(15,2) NOT NULL,
            O_ORDERDATE      DATE NOT NULL , 
            O_ORDERPRIORITY  CHAR(15) NOT NULL, 
            O_CLERK          CHAR(15) NOT NULL , 
            O_SHIPPRIORITY   BIGINT NOT NULL,
            O_COMMENT        VARCHAR(79) NOT NULL
    )
    with (orientation = column,COMPRESSION=MIDDLE)
    distribute by hash(O_ORDERKEY);
    
    DROP TABLE if exists lineitem;
    CREATE TABLE lineitem
    (
            L_ORDERKEY    BIGINT NOT NULL,
            L_PARTKEY     BIGINT NOT NULL, 
            L_SUPPKEY     BIGINT NOT NULL,
            L_LINENUMBER  BIGINT 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  CHAR(1) NOT NULL,
            L_LINESTATUS  CHAR(1) NOT NULL,
            L_SHIPDATE    DATE NOT NULL, 
            L_COMMITDATE  DATE NOT NULL ,
            L_RECEIPTDATE DATE NOT NULL, 
            L_SHIPINSTRUCT CHAR(25) NOT NULL, 
            L_SHIPMODE     CHAR(10) NOT NULL, 
            L_COMMENT      VARCHAR(44) NOT NULL
    )
    with (orientation = column,COMPRESSION=MIDDLE)
    distribute by hash(L_ORDERKEY);
    

  3. Create a foreign table, which is used to identify and associate the source data on OBS.

    • <obs_bucket_name> indicates the OBS bucket name corresponding to the region where DWS is located. For details about supported regions, see Supported Regions. The OBS bucket and sample data have been preset in the system, and you do not need to create them. In this manual, the CN-Hong Kong region is used and set <obs_bucket_name> to dws-demo-ap-southeast-1. OBS bucket data cannot be accessed across regions. For example, if the cluster is located in CN-Hong Kong, you cannot set <obs_bucket_name> to the bucket name of another region.
    • Replace <Access_Key_Id> and <Secret_Access_Key> with the actual values obtained in Making Preparations.
    • Hard-coded or plaintext AK/SK is risky. For security, encrypt your AK/SK and store them in the configuration file or environment variables.
      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    DROP FOREIGN table if exists region_ft;
    CREATE FOREIGN TABLE region_ft
    (
            like region
    )                    
    SERVER gsmpp_server 
    OPTIONS (
            encoding 'utf8',
            location 'obs://<obs_bucket_name>/tpch/region.tbl',
            format 'text',
            delimiter '|',
            access_key '<Access_Key_Id>',
            secret_access_key '<Secret_Access_Key>',
            chunksize '64',
            IGNORE_EXTRA_DATA 'on'
    );
     
    DROP FOREIGN table if exists nation_ft;
    CREATE FOREIGN TABLE nation_ft
    (
            like nation
    )
    SERVER gsmpp_server 
    OPTIONS (
             encoding 'utf8',
             location 'obs://<obs_bucket_name>/tpch/nation.tbl',
             format 'text',
             delimiter '|',
             access_key '<Access_Key_Id>',
             secret_access_key '<Secret_Access_Key>',
             chunksize '64',
             IGNORE_EXTRA_DATA 'on'
    );
     
    DROP FOREIGN table if exists supplier_ft;
    CREATE FOREIGN TABLE supplier_ft
    (
            like supplier
    )
    SERVER gsmpp_server 
    OPTIONS (
            encoding 'utf8',
            location 'obs://<obs_bucket_name>/tpch/supplier.tbl',
            format 'text',
            delimiter '|',
            access_key '<Access_Key_Id>',
            secret_access_key '<Secret_Access_Key>',
            chunksize '64',
            IGNORE_EXTRA_DATA 'on'
    );
     
    DROP FOREIGN table if exists customer_ft;
    CREATE FOREIGN TABLE customer_ft
    (
            like customer
    )
    SERVER gsmpp_server 
    OPTIONS (
            encoding 'utf8',
            location 'obs://<obs_bucket_name>/tpch/customer.tbl',
            format 'text',
            delimiter '|',
            access_key '<Access_Key_Id>',
            secret_access_key '<Secret_Access_Key>',
            chunksize '64',
            IGNORE_EXTRA_DATA 'on'
    );
    DROP FOREIGN table if exists part_ft;
    CREATE FOREIGN TABLE part_ft
    (
            like part
    
    )
    SERVER gsmpp_server 
    OPTIONS (
            encoding 'utf8',
            location 'obs://<obs_bucket_name>/tpch/part.tbl',
            format 'text',
            delimiter '|',
            access_key '<Access_Key_Id>',
            secret_access_key '<Secret_Access_Key>',
            chunksize '64',
            IGNORE_EXTRA_DATA 'on'
    );
    DROP FOREIGN table if exists partsupp_ft;
    CREATE FOREIGN TABLE partsupp_ft
    (
            like partsupp
    )
    SERVER gsmpp_server 
    OPTIONS (
            encoding 'utf8',
            location 'obs://<obs_bucket_name>/tpch/partsupp.tbl',
            format 'text',
            delimiter '|',
            access_key '<Access_Key_Id>',
            secret_access_key '<Secret_Access_Key>',
            chunksize '64',
            IGNORE_EXTRA_DATA 'on'
    );
    DROP FOREIGN table if exists orders_ft;
    CREATE FOREIGN TABLE orders_ft
    (
            like orders
    )
    SERVER gsmpp_server 
    OPTIONS (
            encoding 'utf8',
            location 'obs://<obs_bucket_name>/tpch/orders.tbl',
            format 'text',
            delimiter '|',
            access_key '<Access_Key_Id>',
            secret_access_key '<Secret_Access_Key>',
            chunksize '64',
            IGNORE_EXTRA_DATA 'on'
    );
    DROP FOREIGN table if exists lineitem_ft;
    CREATE FOREIGN TABLE lineitem_ft
    (
            like lineitem
    )
    SERVER gsmpp_server 
    OPTIONS (
            encoding 'utf8',
            location 'obs://<obs_bucket_name>/tpch/lineitem.tbl',
            format 'text',
            delimiter '|',
            access_key '<Access_Key_Id>',
            secret_access_key '<Secret_Access_Key>',
            chunksize '64',
            IGNORE_EXTRA_DATA 'on'
    );
    

  4. Copy and execute the following statements to import the foreign table data to the corresponding database table.

    Run the insert command to import the data in the OBS foreign table to the DWS database table. The database kernel concurrently imports the OBS data at a high speed to DWS.

    1
    2
    3
    4
    5
    6
    7
    8
    INSERT INTO lineitem SELECT * FROM lineitem_ft;
    INSERT INTO part SELECT * FROM part_ft;
    INSERT INTO partsupp SELECT * FROM partsupp_ft;
    INSERT INTO customer SELECT * FROM customer_ft;
    INSERT INTO supplier SELECT * FROM supplier_ft;
    INSERT INTO nation SELECT * FROM nation_ft;
    INSERT INTO region SELECT * FROM region_ft;
    INSERT INTO orders SELECT * FROM orders_ft;
    

    It takes 10 minutes to import data.

Step 2: Performing Multi-Table Analysis and Theme Analysis

The following uses standard TPC-H query as an example to demonstrate how to perform basic data query on DWS.

Before querying data, run the Analyze command to generate statistics related to the database table. The statistics data is stored in system table PG_STATISTIC and is useful when you run the planner, which provides you with an efficient query execution plan.

The following are querying examples:

  • Querying revenue of a supplier in a region (TPCH-Q5)

    By executing the TPCH-Q5 query statement, you can query the revenue statistics of a spare parts supplier in a region. The revenue is calculated based on sum( l_extendedprice * (1 - l_discount)). The statistics can be used to determine whether a local allocation center needs to be established in a given region.

    Copy and execute the following TPCH-Q5 statement for query. This statement features multi-table join query with GROUP BY, ORDER BY, and AGGREGATE.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    SELECT
    n_name,
    sum(l_extendedprice * (1 - l_discount)) as revenue
    FROM
    customer,
    orders,
    lineitem,
    supplier,
    nation,
    region
    where
    c_custkey = o_custkey
    and l_orderkey = o_orderkey
    and l_suppkey = s_suppkey
    and c_nationkey = s_nationkey
    and s_nationkey = n_nationkey
    and n_regionkey = r_regionkey
    and r_name = 'ASIA'
    and o_orderdate >= '1994-01-01'::date
    and o_orderdate < '1994-01-01'::date + interval '1 year'
    group by
    n_name
    order by
    revenue desc;
    
  • Querying relationships between spare parts and suppliers (TPCH-Q16)

    By executing the TPCH-Q16 query statement, you can obtain the number of suppliers that can supply spare parts with the specified contribution conditions. This information can be used to determine whether there are sufficient suppliers when the order quantity is large and the task is urgent.

    Copy and execute the following TPCH-Q16 statement for query. The statement features multi-table connection operations with group by, sort by, aggregate, deduplicate, and NOT IN subquery.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    SELECT
    p_brand,
    p_type,
    p_size,
    count(distinct ps_suppkey) as supplier_cnt
    FROM
    partsupp,
    part
    where
    p_partkey = ps_partkey
    and p_brand <> 'Brand#45'
    and p_type not like 'MEDIUM POLISHED%'
    and p_size in (49, 14, 23, 45, 19, 3, 36, 9)
    and ps_suppkey not in (
            select
            s_suppkey
            from
            supplier
            where
            s_comment like '%Customer%Complaints%'
    )
    group by
    p_brand,
    p_type,
    p_size
    order by
    supplier_cnt desc,
    p_brand,
    p_type,
    p_size
    limit 100;
    
  • Querying revenue loss of small orders (TPCH-Q17)

    You can query the average annual revenue loss if there are no small orders. Filter out small orders that are lower than the 20% of the average supply volume, and calculate the total amount of those small orders to figure out the average annual revenue loss.

    Copy and execute the following TPCH-Q17 statement for query. The statement features multi-table connection operations with aggregate and aggregate subquery.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    SELECT
    sum(l_extendedprice) / 7.0 as avg_yearly
    FROM
    lineitem,
    part
    where
    p_partkey = l_partkey
    and p_brand = 'Brand#23'
    and p_container = 'MED BOX'
    and l_quantity < (
            select 0.2 * avg(l_quantity)
            from lineitem
            where l_partkey = p_partkey
    );