入门指南

从零开始,创建您的第一个数据库集群,导入数据并完成 TPC-H 测试。

准备工作

获取账户

如果您还没有 HashData 的账户,可以点击申请, 我们的工作人员会与您联系。

如果您已经拥有 HashData 的账户,可以登陆控制台。 您将在控制台创建您的第一个数据库集群。

确认配额

当您成功登陆控制台之后,您可以在总览页面看到您的配额情况。 为了完成本章节的工作,您需要确认你至少拥有一个元数据集群配额、一个计算集群配额、13 个云主机配额和相应的 CPU、内存配额。 当您的配额不足时,创建集群会报错。您可以通过工单申请提高配额。

安装客户端工具

您可以使用任何与 PostgreSQL 数据库 9.3 及以上版本兼容的客户端工具连接 HashData 数据库, 我们建议您下载并使用 DBWeaver 连接 HashData 数据库。

如果您的客户端工具需要您配置数据库驱动程序,那么您需要选择 PostgreSQL 数据库驱动程序。 连接数据库使用的 IP 地址是您稍后创建并绑定在计算集群主节点上的公网 IP 地址, 端口号使用默认的 5432 端口。

您稍后会在创建元数据集群时,填写默认数据库名称、默认用户名称和密码。 您将使用这些信息登陆 HashData 数据库。

如果您习惯使用命令行工具,可以使用 PostgreSQL 数据库命令行工具连接 HashData 数据库。

# Redhat/Centos:
# yum install postgresql

# Ubuntu:
# apt-get install postgresql-client

# MacOS
# brew install postgresql

元数据集群

HashData 数据库采用存储、元数据与计算分离的三层架构, 元数据集群负责维护数据库中的表结构等状态信息, 因此首先需要您创建一个元数据集群。

您可以在数据仓库页面,点击 新建元数据服务 按钮创建一个元数据集群。 对于测试环境,您可以完全采用默认配置,在填入集群名称后,默认数据库名称、默认数据库用户和密码,点击 下一步 完成集群的创建。 创建元数据集群大约需要 10 分钟时间,请您耐心等待。 您可以刷新页面查看创建结果。

计算集群

计算集群是您的 SQL 语句真正运行的地方, 计算集群是没有状态的,你可以随时按需创建一个或者多个计算集群, 当然也可以删除计算集群。当您删除计算集群时,您的数据并不会被删除。只有删除元数据集群时,才会删除您的用户数据。

你可以在数据仓库页面,点击 新建数据仓库 按钮创建一个计算集群。 对于测试环境,您可以完全采用默认配置,在填入集群名称后,点击 下一步 完成集群的创建。 创建元数据集群大约需要 5 分钟时间,请您耐心等待。 您可以刷新页面查看创建结果。

连接数据库

您需要一个为计算集群绑定一个 公网 IP 才能访问。 您可以子 公网 IP 页面,点击创建按钮申请一个公网 IP,然后在计算集群的详情页,将公网 IP 绑定到计算集群的主节点。

然后您可以通过这个公网 IP,使用默认的 5432 端口,用任何与 PostgreSQL 数据库 9.3 及以上版本兼容的客户端工具连接 HashData 数据库。 此时,您已经可以通过 SQL 语句创建数据库对象了。

导入数据

接下来,我们指导您导入 TPC-H 标准测试集数据。

这里所采用的数据集和查询是商业智能计算测试 TPC-H。 TPC-H 是美国交易处理效益委员会组织制定的用来模拟决策支持类应用的一个测试集。 TPC-H 实现了一个数据仓库,共包含 8 个基本表,其数据量可以设定从 1G 到 3T 不等。 在这个样例中,我们选择了 1G 的数据集。

创建 TPC-H 数据表

CREATE TABLE NATION  ( 
    N_NATIONKEY  INTEGER NOT NULL,
    N_NAME       CHAR(25) NOT NULL,
    N_REGIONKEY  INTEGER NOT NULL,
    N_COMMENT    VARCHAR(152));

CREATE TABLE REGION  ( 
    R_REGIONKEY  INTEGER NOT NULL,
    R_NAME       CHAR(25) NOT NULL,
    R_COMMENT    VARCHAR(152));

CREATE TABLE PART  ( 
    P_PARTKEY     INTEGER 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        INTEGER NOT NULL,
    P_CONTAINER   CHAR(10) NOT NULL,
    P_RETAILPRICE DECIMAL(15,2) NOT NULL,
    P_COMMENT     VARCHAR(23) NOT NULL );

CREATE TABLE SUPPLIER ( 
    S_SUPPKEY     INTEGER NOT NULL,
    S_NAME        CHAR(25) NOT NULL,
    S_ADDRESS     VARCHAR(40) NOT NULL,
    S_NATIONKEY   INTEGER NOT NULL,
    S_PHONE       CHAR(15) NOT NULL,
    S_ACCTBAL     DECIMAL(15,2) NOT NULL,
    S_COMMENT     VARCHAR(101) NOT NULL);

CREATE TABLE PARTSUPP ( 
    PS_PARTKEY     INTEGER NOT NULL,
    PS_SUPPKEY     INTEGER NOT NULL,
    PS_AVAILQTY    INTEGER NOT NULL,
    PS_SUPPLYCOST  DECIMAL(15,2)  NOT NULL,
    PS_COMMENT     VARCHAR(199) NOT NULL );

CREATE TABLE CUSTOMER ( 
    C_CUSTKEY     INTEGER NOT NULL,
    C_NAME        VARCHAR(25) NOT NULL,
    C_ADDRESS     VARCHAR(40) NOT NULL,
    C_NATIONKEY   INTEGER 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);

CREATE TABLE ORDERS (
    O_ORDERKEY       INT8 NOT NULL,
    O_CUSTKEY        INTEGER 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   INTEGER NOT NULL,
    O_COMMENT        VARCHAR(79) NOT NULL);

CREATE TABLE LINEITEM ( 
    L_ORDERKEY    INT8 NOT NULL,
    L_PARTKEY     INTEGER NOT NULL,
    L_SUPPKEY     INTEGER NOT NULL,
    L_LINENUMBER  INTEGER 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);

创建外部表

我们使用外部表将 TPC-H 数据集加载进入 HashData 数据库。 外部表是一种特殊的数据库对象,它在数据库中仅仅保存表结构定义,而他的数据保存在数据库的外部。 我们这个例子中,外部表的数据保存在青云的对象存储中。

外部表通常用来加载数据,通过外部表加载数据是并行的,性能可以随着数据库节点的增加而线性扩展。

CREATE READABLE EXTERNAL TABLE e_NATION (LIKE NATION)
LOCATION ('qs://hashdata-public.pek3a.qingstor.com/tpch/1g/nation/') FORMAT 'csv';

CREATE READABLE EXTERNAL TABLE e_REGION (LIKE REGION)
LOCATION ('qs://hashdata-public.pek3a.qingstor.com/tpch/1g/region/') FORMAT 'csv';

CREATE READABLE EXTERNAL TABLE e_PART (LIKE PART)
LOCATION ('qs://hashdata-public.pek3a.qingstor.com/tpch/1g/part/') FORMAT 'csv';

CREATE READABLE EXTERNAL TABLE e_SUPPLIER (LIKE SUPPLIER)
LOCATION ('qs://hashdata-public.pek3a.qingstor.com/tpch/1g/supplier/') FORMAT 'csv';

CREATE READABLE EXTERNAL TABLE e_PARTSUPP (LIKE PARTSUPP)
LOCATION ('qs://hashdata-public.pek3a.qingstor.com/tpch/1g/partsupp/') FORMAT 'csv';

CREATE READABLE EXTERNAL TABLE e_CUSTOMER (LIKE CUSTOMER)
LOCATION ('qs://hashdata-public.pek3a.qingstor.com/tpch/1g/customer/') FORMAT 'csv';

CREATE READABLE EXTERNAL TABLE e_ORDERS (LIKE ORDERS)
LOCATION ('qs://hashdata-public.pek3a.qingstor.com/tpch/1g/orders/') FORMAT 'csv';

CREATE READABLE EXTERNAL TABLE e_LINEITEM (LIKE LINEITEM)
LOCATION ('qs://hashdata-public.pek3a.qingstor.com/tpch/1g/lineitem/') FORMAT 'csv';

加载数据

外部表可以像不同数据表一样通过 SELECT 读取出来,我们这里通过外部表读取对象存储中的 TPC-H 数据文件, 然后通过 INSERT 语句插入数据库表中。

INSERT INTO NATION SELECT * FROM e_NATION;  
INSERT INTO REGION SELECT * FROM e_REGION;  
INSERT INTO PART SELECT * FROM e_PART;  
INSERT INTO SUPPLIER SELECT * FROM e_SUPPLIER;  
INSERT INTO PARTSUPP SELECT * FROM e_PARTSUPP;  
INSERT INTO CUSTOMER SELECT * FROM e_CUSTOMER;  
INSERT INTO ORDERS SELECT * FROM e_ORDERS;  
INSERT INTO LINEITEM SELECT * FROM e_LINEITEM;

开始查询

TPC-H 基准测试包括 22 个查询,其主要评价指标是各个查询的响应时间,即从提交查询到结果返回所需时间。 这里只提供了前三条查询语句。关于 TPC-H 完整 22 条查询语句以及详细介绍可参考 TPC-H 主页

 -- This query reports the amount of business that was billed, shipped, and returned.

 select  
    l_returnflag,  
    l_linestatus,  
    sum(l_quantity) as sum_qty,  
    sum(l_extendedprice) as sum_base_price,  
    sum(l_extendedprice * (1 - l_discount)) as sum_disc_price,  
    sum(l_extendedprice * (1 - l_discount) * (1 + l_tax)) as sum_charge,  
    avg(l_quantity) as avg_qty,  
    avg(l_extendedprice) as avg_price,  
    avg(l_discount) as avg_disc,  
    count(*) as count_order  
from  
    lineitem
 where  
    l_shipdate <=  '1998-12-01'  
group by  
    l_returnflag,  
    l_linestatus  
order by  
    l_returnflag,  
    l_linestatus;

 -- This query finds which supplier should be selected to place an order for a given part in a given region.

 select  
    s.s_acctbal,  
    s.s_name,  
    n.n_name,  
    p.p_partkey,  
    p.p_mfgr,  
    s.s_address,  
    s.s_phone,  
    s.s_comment  
from  
    supplier s,  
    partsupp ps,  
    nation n,  
    region r,  
    part p,  
    (select p_partkey, min(ps_supplycost) as min_ps_cost  
            from  
                    part,  
                    partsupp ,  
                    supplier,  
                    nation,  
                    region  
            where  
                    p_partkey=ps_partkey  
                    and s_suppkey = ps_suppkey  
                    and s_nationkey = n_nationkey  
                    and n_regionkey = r_regionkey  
                    and r_name = 'EUROPE'  
            group by p_partkey ) g  
where  
    p.p_partkey = ps.ps_partkey  
    and g.p_partkey = p.p_partkey  
    and g. min_ps_cost = ps.ps_supplycost  
    and s.s_suppkey = ps.ps_suppkey  
    and p.p_size = 45  
    and p.p_type like '%NICKEL'  
    and s.s_nationkey = n.n_nationkey  
    and n.n_regionkey = r.r_regionkey  
    and r.r_name = 'EUROPE'  
order by  
    s.s_acctbal desc,  
    n.n_name,  
    s.s_name,  
    p.p_partkey  
LIMIT 100;
 -- This query retrieves the 10 unshipped orders with the highest value.

 select  
    l_orderkey,  
    sum(l_extendedprice * (1 - l_discount)) as revenue,  
    o_orderdate,  
    o_shippriority  
from  
    customer,  
    orders,  
    lineitem  
where  
    c_mktsegment = 'MACHINERY'  
    and c_custkey = o_custkey  
    and l_orderkey = o_orderkey  
    and o_orderdate < '1995-03-15'  
    and l_shipdate >  '1995-03-15'  
group by  
    l_orderkey,  
    o_orderdate,  
    o_shippriority  
order by  
    revenue desc,  
    o_orderdate  
LIMIT 10;