华为云原生之数据仓库服务GaussDB(DWS)的深度使用与应用实践

2年前 (2022) 程序员胖胖胖虎阿
266 0 0

一、GaussDB(DWS)简介

① 什么是 GaussDB(DWS)?

  • 数据仓库服务 GaussDB(DWS) 是一种基于华为云基础架构和平台的在线数据处理数据库,提供即开即用、可扩展且完全托管的分析型数据库服务。
  • GaussDB(DWS) 是基于华为融合数据仓库 GaussDB 产品的云原生服务 ,兼容标准 ANSI SQL 99 和 SQL 2003,同时兼容 PostgreSQL/Oracle 数据库生态,为各行业 PB 级海量大数据分析提供有竞争力的解决方案。

华为云原生之数据仓库服务GaussDB(DWS)的深度使用与应用实践

  • GaussDB(DWS) 基于 Shared-nothing 分布式架构,具备 MPP (Massively Parallel Processing) 大规模并行处理引擎,由众多拥有独立且互不共享的 CPU、内存、存储等系统资源的逻辑节点组成。在这样的系统架构中,业务数据被分散存储在多个节点上,数据分析任务被推送到数据所在位置就近执行,并行地完成大规模的数据处理工作,实现对数据处理的快速响应。

华为云原生之数据仓库服务GaussDB(DWS)的深度使用与应用实践

② 数据仓库类型

  • 云数仓:高性价比,支持冷热数据分析,存储、计算弹性伸缩,并按需、按量计价。适用于“库、仓、市、湖”一体化的融合分析业务,适合 50 节点以内的中小型数据仓库。
  • 标准数仓:高性能、高扩展、高可用、易运维的企业级数据仓库,支持 2048 节点、20PB 级超大规模数据分析能力,适用于大型企业数仓,上云后体验不变。
  • IoT 数仓:在标准数仓基础上,提供高效的时序计算和 IoT 分析能力,支持实时和历史数据关联,适用于物联网、IoT 等实时分析场景。
  • 实时数仓:在大规模数据查询和分析能力基础上,提供高并发、高性能、低时延的事务处理能力。适用于 HTAP 混合负载场景,“一库两用,生产即分析”。
    • 实时数仓单机模式不支持演进到分布式模式,因此不支持扩缩容、逻辑集群等操作;
    • 实时数仓单机模式暂不支持快照、DMS 监控、资源池队列等功能;
    • 实时数仓单机模式中,原有指定分布列语法将被忽略,此外暂不支持 job 定时任务、sequence 等功能。

③ GaussDB(DWS)的应用场景

  • 数据仓库迁移:

华为云原生之数据仓库服务GaussDB(DWS)的深度使用与应用实践

  • 大数据融合分析:

华为云原生之数据仓库服务GaussDB(DWS)的深度使用与应用实践

  • 增强型 ETL 和实时 BI 分析:

华为云原生之数据仓库服务GaussDB(DWS)的深度使用与应用实践

  • 实时数据分析:

华为云原生之数据仓库服务GaussDB(DWS)的深度使用与应用实践

④ GaussDB(DWS)优势

  • 易使用:一站式可视化便捷管理、与大数据无缝集成、提供一键式异构数据库迁移工具;
  • 高性能:云化分布式架构、查询高性能万亿数据秒级响应、数据加载快;
  • 易扩展:按需扩展、扩容后性能线性提升、扩容不中断业务;
  • 高可靠:支持分布式事务 ACID 数据强一致保证、全方位 HA 设计、数据安全可靠;
  • 低成本:按需付费、门槛低。

⑤ GaussDB(DWS)功能

(A)企业级数据仓库和标准 SQL 的支持

  • GaussDB(DWS)提供 PB(petabyte)级高性能数据库,主要体现在:
    • MPP 大规模并行处理框架,支持行列混存、向量化执行,实现万亿数据关联分析秒级响应;
    • 内存计算,基于 Bloom Filter 的 Hash Join 优化,性能提升 2~10 倍;
    • 基于电信技术优化的大规模集群通信,提升计算节点间的传输效率;
    • 基于代价的智能优化器,根据集群规模、数据量、生成最优计划,提高执行效率。
  • GaussDB(DWS)具有完备的 SQL 能力:
    • 支持 SQL 92、SQL 2003 标准,支持存储过程,支持 GBK 和 UTF-8 字符集,支持 SQL 标准函数与 OLAP 分析函数;
    • 兼容 PostgreSQL 生态,与主流第三方数据库 ETL,BI(business intelligence)工具厂商对接认证。

(B)多样化的数据导入方式

  • 从 OBS(对象存储服务)并行导入数据;
  • 使用 GDS(General Data Service)从远端服务器导入数据;
  • 通过 INSERT 语句直接写入数据;
  • 使用 COPY FROM STDIN 导入数据;
  • 使用 gsql 元命令导入数据;
  • 从 MRS(MapReduce 服务)导入数据到集群;
  • 从 DIS(数据接入服务)导入流式数据到 GaussDB(DWS);
  • 使用 CDM(云数据迁移服务)迁移数据到 GaussDB(DWS);
  • 使用 DSC 工具迁移 SQL 脚本;
  • 支持主流第三方 ETL 工具进行数据导入。

(C)应用程序接口

  • 支持调用 JDBC(Java database connectivity)接口;
  • 支持调用 ODBC(Open Database Connectivity)接口;
  • 支持 Python 第三方库 psycopg2 等标准接口。

(D)支持多种数据库工具

  • 支持 gsql 工具;
  • 支持 Data Studio 工具;
  • 支持 GDS 工具;
  • 支持 DSC SQL 语法迁移工具。

二、GaussDB(DWS) 使用流程

① 准备工作

  • 在创建 GaussDB(DWS) 集群时需要指定一个端口供 SQL 客户端或应用程序通过该端口访问集群;
  • 如果客户端机器位于防火墙之后,则需要有一个可用的开放端口,这样才能从 SQL 客户端工具连接到集群并进行查询分析;
  • 如果不了解可用的开放端口,则请联系网络管理员,在防火墙中确定一个开放端口,GaussDB(DWS) 支持的端口范围为 8000~30000;
  • 在集群创建之后无法更改集群的端口号,请务必确保在集群创建过程中指定的端口为可用的开放端口。

② 创建集群

  • 登录 GaussDB(DWS) 管理控制台,选择“大数据 > 数据仓库服务”,进入 GaussDB(DWS) 服务的控制台页面:

华为云原生之数据仓库服务GaussDB(DWS)的深度使用与应用实践

  • 单击左侧导航栏的“集群管理”,再选择“创建数据仓库集群”:

华为云原生之数据仓库服务GaussDB(DWS)的深度使用与应用实践

  • 选择”区域“,在选择“产品类型”、“CPU架构”和“节点规格”:

华为云原生之数据仓库服务GaussDB(DWS)的深度使用与应用实践

  • 填写“集群配置”参数:

华为云原生之数据仓库服务GaussDB(DWS)的深度使用与应用实践

  • 配置“网络”:

华为云原生之数据仓库服务GaussDB(DWS)的深度使用与应用实践

  • 设置高级配置,选择“自定义”时,可以设置以下高级配置参数,若选择“默认配置”,再购买相应的折扣套餐即可创建成功集群:

华为云原生之数据仓库服务GaussDB(DWS)的深度使用与应用实践

  • 最后单击“立即创建”,进入“规格详情”页面,然后提交即可。

③ 连接集群

  • 如果已经成功创建 GaussDB(DWS) 集群,就可以使用 SQL 客户端工具或者 JDBC(Java database connectivity)/ODBC(Open Database Connectivity)等第三方驱动程序连接集群,访问集群中的数据库。
  • 进入 GaussDB(DWS) 控制台的“连接管理”页面,就可以下载 SQL 客户端工具和 JDBC/ODBC 驱动程序。

(A)获取集群连接地址

  • 在 GaussDB(DWS) 的管理控制台的左侧导航栏中,单击“连接管理”,在“数据仓库连接信息”区域,选择一个可用的集群名称(只能选择状态为可用的集群):

华为云原生之数据仓库服务GaussDB(DWS)的深度使用与应用实践

  • 查看并获取集群的连接信息:“内网访问地址”、“公网访问地址”、“弹性负载均衡地址”、“JDBC 连接字符串(内网)”、“JDBC 连接字符串(公网)”、“ODBC 连接字符串”。

(B)使用 Data Studio 连接到集群数据库

  • GaussDB(DWS) 提供基于 Windows 平台的 Data Studio 图形界面客户端,该工具依赖 JDK,需先在客户端主机上 安装 JDK。
  • 登录 GaussDB(DWS) 管理控制台,单击“连接管理”,在“下载客户端和驱动”页面,下载“Data Studio 图形界面客户端”:

华为云原生之数据仓库服务GaussDB(DWS)的深度使用与应用实践

  • 解压下载的客户端软件包(32 位或 64 位)到需要安装的路径,打开安装目录,双击 Data Studio,启动 Data Studio 客户端:

华为云原生之数据仓库服务GaussDB(DWS)的深度使用与应用实践

  • 在主菜单中选择 “文件>新建连接”:

华为云原生之数据仓库服务GaussDB(DWS)的深度使用与应用实践

  • 在弹出的“新建/选择数据库连接”页面中,如下图所示,输入连接参数:

华为云原生之数据仓库服务GaussDB(DWS)的深度使用与应用实践
华为云原生之数据仓库服务GaussDB(DWS)的深度使用与应用实践

  • 单击“确定”建立数据库连接:

华为云原生之数据仓库服务GaussDB(DWS)的深度使用与应用实践

  • 连接集群后,就可以创建和管理数据库、管理用户及权限、导入或导出数据,以及查询和分析数据(“数据库的操作与管理”请参考下文的“GaussDB(DWS)的基本使用”)。

(C)管理数据库连接

  • 查看最大连接数:
SHOW max_connections;
  • 查看连接到指定用户 dbadmin 的会话连接数上限:
SELECT ROLNAME,ROLCONNLIMIT FROM PG_ROLES WHERE ROLNAME='dbadmin';
  • 查看指定用户 dbadmin 已使用的会话连接数:
SELECT COUNT(*) FROM V$SESSION WHERE USERNAME='dbadmin';
  • 查看连接到指定数据库 gaussdb 的会话连接数上限:
SELECT DATNAME,DATCONNLIMIT FROM PG_DATABASE WHERE DATNAME='gaussdb';
  • 查看指定数据库 gaussdb 上已使用的会话连接数:
SELECT COUNT(*) FROM PG_STAT_ACTIVITY WHERE DATNAME='gaussdb';
  • 查看所有用户已使用的会话连接数:
SELECT COUNT(*) FROM V$SESSION;

④ 管理和监控集群

(A)管理集群

  • 在“大数据”列表中,单击“数据仓库服务”,就可以进入数据仓库服务管理控制台页面。
  • 可以查看集群状态,修改集群配置,添加集群标签,对集群进行扩容、重启、删除等管理操作。

(B)管理快照

  • 快照是对 GaussDB(DWS) 集群在某一时间点的一次全量数据和增量数据的备份,记录了当前数据库的数据以及集群的相关信息,其中包括节点数量、节点规格和管理员用户名称等。
  • 从快照恢复到集群时,GaussDB(DWS) 会根据快照记录的集群信息来创建新集群,然后从快照记录的数据中还原数据库信息。
  • 在左侧导航栏中,单击“快照管理”,在快照列表中,默认显示用户所有的快照:

华为云原生之数据仓库服务GaussDB(DWS)的深度使用与应用实践

  • 在快照列表中,可以查看快照的“快照名称”、“快照状态”、:“集群名称”、“快照类型”和“快照创建时间”。

(C)运维与监控

  • CES 监控集群:
    • 登录 GaussDB(DWS) 管理控制台,进入“集群管理”页面,查看集群信息:在集群列表中,在指定集群所在行,单击“查看监控指标”,打开云监控管理控制台(默认显示的是集群监控信息)。可以根据需要,选择指定的监控指标名称以及时间范围,从而显示监控指标的性能曲线。
    • 可以在“监控面板”页面,单击右上角的“添加监控视图”,在弹出的“添加监控视图”窗口中,配置标题和监控项:

华为云原生之数据仓库服务GaussDB(DWS)的深度使用与应用实践

    • 添加成功后,可在“监控面板”区域看到对应的监控视图:

华为云原生之数据仓库服务GaussDB(DWS)的深度使用与应用实践

    • 还可以创建告警规则:

华为云原生之数据仓库服务GaussDB(DWS)的深度使用与应用实践
华为云原生之数据仓库服务GaussDB(DWS)的深度使用与应用实践

    • 配置告警通知,根据界面提示配置参数:

华为云原生之数据仓库服务GaussDB(DWS)的深度使用与应用实践

  • 事件通知:事件是用户集群状态发生变化的记录,它可以是由用户操作触发的(比如审计事件),也有可能是集群服务状态变化引起的(比如集群修复成功或集群修复失败)。
  • 审计日志:
    • GaussDB(DWS) 支持对特定数据库操作记录审计日志,包括:日志保留策略、用户越权访问、存储过程以及对数据库对象的 DML、SELECT、COPY 和 DDL 操作。
    • 审计日志配置后,当 GaussDB(DWS) 集群状态异常,或根据业务需要,用户可以查询审计信息确定故障原因或定位历史操作记录。
    • 通过查看管理控制台审计日志,记录下 GaussDB(DWS) 管理控制台的关键操作事件,比如创建集群、创建快照、重启集群等,记录下的日志可用于支撑安全分析、合规审计、资源跟踪和问题定位等常见应用场景。

三、GaussDB(DWS)的基本使用

① 设置创建数据库的权限

  • 使用 CREATE USER 和 ALTER USER 可以创建和管理数据库用户,数据库集群包含一个或多个已命名数据库,用户和角色在整个集群范围内是共享的,但是其数据并不共享,即用户可以连接任何数据库,但当连接成功后,任何用户都只能访问连接请求里声明的那个数据库。
  • 在用户登录 GaussDB(DWS) 时会对其进行身份验证,用户可以拥有数据库和数据库对象(例如表),并且可以向用户和角色授予对这些对象的权限以控制谁可以访问哪个对象。
  • 创建用户,可以使用 SQL 语句 CREATE USER,例如创建用户 Kody,并设置用户拥有 CREATEDB 属性,如下所示:
CREATE USER Kody WITH CREATEDB PASSWORD 'password';
  • 创建系统管理员,可以使用带有 SYSADMIN 选项的 CREATE USER 语句:
CREATE USER sysadmin WITH SYSADMIN password "Bigdata@123";
  • 删除现有用户,可以使用 DROP USER:
DROP USER user, [user],...;
  • 更改用户帐户(重命名用户或更改密码),可以使用 ALTER USER:
ALTER USER name [ WITH ] option [ ... ]]
  • 查看用户列表,可以查询视图 PG_USER:
SELECT * FROM pg_user;
  • 查看用户属性,可以查询系统表 PG_AUTHID:
SELECT * FROM pg_authid;
  • 创建具有 INDEPENDENT 属性的私有用户:
CREATE USER user_independent WITH INDEPENDENT IDENTIFIED BY "1234@abc";

② 创建和管理数据库

  • GaussDB(DWS)包含两个模板数据库 template0、template1,以及一个默认的用户数据库 gaussdb。CREATE DATABASE 实际上通过拷贝模板数据库来创建新数据库,默认情况下拷贝 template1,但要避免使用客户端或其他手段连接及操作两个模板数据库。
  • 创建一个新的数据库 db_MyData:
CREATE DATABASE db_MyData;
  • 当创建成功时,如下所示:
CREATE DATABASE
  • 查看数据库系统的数据库列表:
\l
  • 通过系统表 pg_database 查询数据库列表:
SELECT datname FROM pg_database;
  • 为数据库设置默认的模式搜索路径:
ALTER DATABASE db_MyData SET search_path TO pa_catalog,public;
ALTER DATABASE
  • 修改数据库表空间:
ALTER DATABASE db_MyData SET TABLESPACE MyData;
ALTER DATABASE
  • 为数据库重新命名:
ALTER DATABASE db_MyData RENAME TO human_MyData;
ALTER DATABASE
  • 删除数据库:
DROP DATABASE human_MyData;
DROP DATABASE

③ GaussDB(DWS) 设置存储模型

  • GaussDB(DWS) 支持行列混合存储,行存储是指将表按行存储到硬盘分区上,列存储是指将表按列存储到硬盘分区上。

华为云原生之数据仓库服务GaussDB(DWS)的深度使用与应用实践

  • 默认情况下,GaussDB(DWS) 创建的表为行存储,数据按行进行存储,即一行数据是连续存储,适用于对数据需要经常更新的场景:
CREATE TABLE customer_t1
(
  state_ID   CHAR(2),
  state_NAME VARCHAR2(40),
  area_ID    NUMBER
);

--删除表
DROP TABLE customer_t1;
  • 如果数据按列进行存储,即一列所有数据是连续存储的,单列查询 IO 小,比行存表占用更少的存储空间,适合数据批量插入、更新较少和以查询为主统计分析类的场景,列存表不适合点查询:
CREATE TABLE customer_t2
(
  state_ID   CHAR(2),
  state_NAME VARCHAR2(40),
  area_ID    NUMBER
)
WITH (ORIENTATION = COLUMN);

--删除表
DROP TABLE customer_t2;

④ 创建与管理表

(A)创建表

  • 执行如下命令创建表:
CREATE TABLE customer_t1
(
    c_customer_sk             integer,
    c_customer_id             char(5),
    c_first_name              char(6),
    c_last_name               char(8)
)
with (orientation = column,compression=middle)
distribute by hash (c_last_name);
  • 当创建成功时,如下所示:
CREATE TABLE

(B) 向表中插入数据

  • 建立需要使用的表 table1、table2:
CREATE TABLE table1(id int, a char(6), b varchar(6),c varchar(6)) ;
CREATE TABLE table2(id int, a char(20), b varchar(20),c varchar(20)) ;
  • 向表 customer_t1 中插入一行:
    • 数据值是按照这些字段在表中出现的顺序列出的,并且用逗号分隔,通常数据值是文本(常量),但也允许使用标量表达式:
INSERT INTO customer_t1(c_customer_sk, c_customer_id, c_first_name) VALUES (3769, 'hello', 'Grace');
    • 如果用户已经知道表中字段的顺序,也可无需列出表中的字段,以下命令与上面的命令效果相同:
INSERT INTO customer_t1 VALUES (3769, 'hello', 'Grace');
    • 如果用户不知道所有字段的数值,可以忽略其中的一些,没有数值的字段将被填充为字段的缺省值:
INSERT INTO customer_t1 (c_customer_sk, c_first_name) VALUES (3769, 'Grace');

INSERT INTO customer_t1 VALUES (3769, 'hello');
    • 也可以对独立的字段或者整个行明确缺省值:
INSERT INTO customer_t1 (c_customer_sk, c_customer_id, c_first_name) VALUES (3769, 'hello', DEFAULT);

INSERT INTO customer_t1 DEFAULT VALUES;
  • 如果需要在表中插入多行,请使用以下命令:
INSERT INTO customer_t1 (c_customer_sk, c_customer_id, c_first_name) VALUES 
    (6885, 'maps', 'Joes'),
    (4321, 'tpcds', 'Lily'),
    (9527, 'world', 'James');
  • 如果从指定表插入数据到当前表,例如在数据库中创建了一个表 customer_t1 的备份表 customer_t2,现在需要将表 customer_t1 中的数据插入到表 customer_t2 中,则可以执行如下命令:
CREATE TABLE customer_t2
(
    c_customer_sk             integer,
    c_customer_id             char(5),
    c_first_name              char(6),
    c_last_name               char(8)
) ;

INSERT INTO customer_t2 SELECT * FROM customer_t1;
  • 删除备份表:
DROP TABLE customer_t2 CASCADE;

© 更新表中数据

  • 将表 customer_t1 中 c_customer_sk 为 9527 的地域重新定义为 9876:
UPDATE customer_t1 SET c_customer_sk = 9876 WHERE c_customer_sk = 9527;
  • 将表 customer_t1 中 c_customer_sk 为 9527 的地域重新定义为 c_customer_sk + 100:
UPDATE customer_t1 SET c_customer_sk= c_customer_sk + 100 WHERE c_customer_sk= 9527;
  • 将 Public 模式下表 customer_t1 中 c_customer_sk 为 9527 的地域重新定义为 9876:
UPDATE public.customer_t1 SET c_customer_sk= 9876 WHERE c_customer_sk= 9527;
  • 不含 WHERE 子句表示把所有 c_customer_sk 的值增加 100:
UPDATE customer_t1 SET c_customer_sk = c_customer_sk + 100;
  • 将表 customer_t1 中 c_customer_sk 大于 9527 的地域全部重新定义为 9876:
UPDATE customer_t1 SET c_customer_sk = 9876 WHERE c_customer_sk > 9527;
  • 可以在一个 UPDATE 命令中更新更多的字段,方法是在 SET 子句中列出更多赋值,比如:
UPDATE customer_t1 SET  c_customer_id = 'Admin', c_first_name = 'Local' WHERE c_customer_sk

(D) 查看数据

  • 使用系统表 pg_tables 查询数据库所有表的信息:
SELECT * FROM pg_tables;
  • 使用 gsql 的 \d+ 命令查询表的属性:
\d+ customer_t1;
  • 查询表 customer_t1 的数据量:
SELECT count(*) FROM customer_t1;
  • 查询表 customer_t1 的所有数据:
SELECT * FROM customer_t1;
  • 只查询字段 c_customer_sk 的数据:
SELECT c_customer_sk FROM customer_t1;
  • 过滤字段 c_customer_sk 的重复数据:
SELECT DISTINCT( c_customer_sk ) FROM customer_t1;
  • 查询字段 c_customer_sk 为 3869 的所有数据:
SELECT * FROM customer_t1 WHERE c_customer_sk = 3869;
  • 按照字段 c_customer_sk 进行排序:
SELECT * FROM customer_t1 ORDER BY c_customer_sk;

(E)删除表中数据

  • 使用 DELETE 命令删除行,如果删除表 customer_t1 中所有 c_customer_sk 为 3869 的记录:
DELETE FROM customer_t1 WHERE c_customer_sk = 3869;
  • 如果执行如下命令,会删除表中所有的行:
DELETE FROM customer_t1;

TRUNCATE TABLE customer_t1;
  • 删除创建的表:
DROP TABLE customer_t1;

⑤ 创建和管理 schema

(A)创建 schema

  • 创建一个 schema:
CREATE SCHEMA myschema;
  • 创建成功时,如下所示:
CREATE SCHEMA
  • 在创建 schema 时指定 owner:
CREATE SCHEMA myschema AUTHORIZATION dbadmin;

(B) 使用 schema

  • 在 myschema 下创建 mytable 表:
CREATE TABLE myschema.mytable(id int, name varchar(20));
CREATE TABLE
  • 执行如下命令查询 myschema 下 mytable 表的所有数据:
SELECT * FROM myschema.mytable;
id | name 
----+------
(0 rows)

© schema 的搜索路径

  • 查看搜索路径:
SHOW SEARCH_PATH;
 search_path
----------------
 "$user",public
(1 row)
  • 将搜索路径设置为 myschema、public,首先搜索 myschema:
SET SEARCH_PATH TO myschema, public;
SET

(D) schema 权限控制

  • 查看现有的 schema:
SELECT current_schema();
 current_schema 
----------------
 myschema
(1 row)
  • 创建用户 Kody,并将 myschema 的 usage 权限赋给用户 Kody:
CREATE USER Kody IDENTIFIED BY 'Bigdata@123';
GRANT USAGE ON schema myschema TO Kody;
  • 将用户 Kody 对于 myschema 的 usage 权限收回:
REVOKE USAGE ON schema myschema FROM Kody;

(E) 删除 schema

  • 当 schema 为空时,即该 schema 下没有数据库对象,使用 DROP SCHEMA 命令进行删除,删除名为 nullschema 的空 schema:
DROP SCHEMA IF EXISTS nullschema;
DROP SCHEMA
  • 当 schema 非空时,如果要删除一个 schema 及其包含的所有对象,需要使用 CASCADE 关键字,删除 myschema 及该 schema 下的所有对象:
DROP SCHEMA myschema CASCADE;
DROP SCHEMA
  • 删除用户 Kody:
DROP USER Kody;
DROP USER

⑥ 管理分区表

  • 创建分区表:
CREATE TABLE tpcds.customer_address
(
    ca_address_sk       integer                  NOT NULL   ,
    ca_address_id       character(16)            NOT NULL   ,
    ca_street_number    character(10)                       ,
    ca_street_name      character varying(60)               ,
    ca_street_type      character(15)                       ,
    ca_suite_number     character(10)                       ,
    ca_city             character varying(60)               ,
    ca_county           character varying(30)               ,
    ca_state            character(2)                        ,
    ca_zip              character(10)                       ,
    ca_country           character varying(20)               ,
    ca_gmt_offset       numeric(5,2)                        ,
    ca_location_type    character(20)
)
DISTRIBUTE BY HASH (ca_address_sk)
PARTITION BY RANGE (ca_address_sk)
(
        PARTITION P1 VALUES LESS THAN(5000),
        PARTITION P2 VALUES LESS THAN(10000),
        PARTITION P3 VALUES LESS THAN(15000),
        PARTITION P4 VALUES LESS THAN(20000),
        PARTITION P5 VALUES LESS THAN(25000),
        PARTITION P6 VALUES LESS THAN(30000),
        PARTITION P7 VALUES LESS THAN(40000),
        PARTITION P8 VALUES LESS THAN(MAXVALUE)
)
ENABLE ROW MOVEMENT;
  • 将表 tpcds.customer_address 的数据插入到表 tpcds.web_returns_p2 中:
CREATE TABLE tpcds.web_returns_p2
(
    ca_address_sk       integer                  NOT NULL   ,
    ca_address_id       character(16)            NOT NULL   ,
    ca_street_number    character(10)                       ,
    ca_street_name      character varying(60)               ,
    ca_street_type      character(15)                       ,
    ca_suite_number     character(10)                       ,
    ca_city             character varying(60)               ,
    ca_county           character varying(30)               ,
    ca_state            character(2)                        ,
    ca_zip              character(10)                       ,
    ca_country           character varying(20)               ,
    ca_gmt_offset       numeric(5,2)                        ,
    ca_location_type    character(20)
)
DISTRIBUTE BY HASH (ca_address_sk)
PARTITION BY RANGE (ca_address_sk)
(
        PARTITION P1 VALUES LESS THAN(5000),
        PARTITION P2 VALUES LESS THAN(10000),
        PARTITION P3 VALUES LESS THAN(15000),
        PARTITION P4 VALUES LESS THAN(20000),
        PARTITION P5 VALUES LESS THAN(25000),
        PARTITION P6 VALUES LESS THAN(30000),
        PARTITION P7 VALUES LESS THAN(40000),
        PARTITION P8 VALUES LESS THAN(MAXVALUE)
)
ENABLE ROW MOVEMENT;
CREATE TABLE
INSERT INTO tpcds.web_returns_p2 SELECT * FROM tpcds.customer_address;
INSERT 0 0
  • 修改分区表行迁移属性:
ALTER TABLE tpcds.web_returns_p2 DISABLE ROW MOVEMENT;
ALTER TABLE
  • 删除分区 P8:
ALTER TABLE tpcds.web_returns_p2 DROP PARTITION P8;
ALTER TABLE
  • 增加分区 P8,范围为 40000<= P8<=MAXVALUE:
ALTER TABLE tpcds.web_returns_p2 ADD PARTITION P8 VALUES LESS THAN (MAXVALUE);
ALTER TABLE
  • 重命名分区 P8 为 P_9:
ALTER TABLE tpcds.web_returns_p2 RENAME PARTITION P8 TO P_9;
ALTER TABLE
  • 查询分区 P7:
SELECT * FROM tpcds.web_returns_p2 PARTITION (P7);
SELECT * FROM tpcds.web_returns_p2 PARTITION FOR (35888);
  • 查看分区表信息,可使用系统表 dba_tab_partitions:
select * from dba_tab_partitions where table_name='tpcds.customer_address';
  • 删除分区表:
DROP TABLE tpcds.web_returns_p2;
DROP TABLE

⑦ 管理索引

  • 创建分区表索引 tpcds_web_returns_p2_index1,不指定索引分区的名字:
CREATE INDEX tpcds_web_returns_p2_index1 ON tpcds.web_returns_p2 (ca_address_id) LOCAL;
  • 创建分区索引 tpcds_web_returns_p2_index2,并指定索引分区的名字:
CREATE INDEX tpcds_web_returns_p2_index2 ON tpcds.web_returns_p2 (ca_address_sk) LOCAL
(
    PARTITION web_returns_p2_P1_index,
    PARTITION web_returns_p2_P2_index TABLESPACE example3,
    PARTITION web_returns_p2_P3_index TABLESPACE example4,
    PARTITION web_returns_p2_P4_index,
    PARTITION web_returns_p2_P5_index,
    PARTITION web_returns_p2_P6_index,
    PARTITION web_returns_p2_P7_index,
    PARTITION web_returns_p2_P8_index
) TABLESPACE example2;
  • 重命名索引分区:
ALTER INDEX tpcds.tpcds_web_returns_p2_index2 RENAME PARTITION web_returns_p2_P8_index TO web_returns_p2_P8_index_new;
  • 查询系统和用户定义的所有索引:
SELECT RELNAME FROM PG_CLASS WHERE RELKIND='i';
  • 删除索引:
DROP INDEX tpcds.tpcds_web_returns_p2_index1;
DROP INDEX tpcds.tpcds_web_returns_p2_index2;

⑧ 管理视图

  • 创建视图:
CREATE OR REPLACE VIEW MyView AS SELECT * FROM tpcds.web_returns WHERE trunc(wr_refunded_cash) > 10000;
CREATE VIEW
  • 查询视图:
SELECT * FROM MyView;
  • 重建视图:
ALTER VIEW MyView REBUILD;
ALTER VIEW
  • 删除视图:
DROP VIEW MyView;
DROP VIEW

⑨ 管理序列

  • 创建序列:
CREATE SEQUENCE seq1 cache 100;
  • 指定为某一字段的默认值,使该字段具有唯一标识属性:
CREATE TABLE T2 
( 
    id   int not null default nextval('seq1'),
    name text
);
  • 指定序列与列的归属关系:
ALTER SEQUENCE seq1 OWNED BY T2.id;

⑩ 管理定时任务

  • 创建测试表:
CREATE TABLE test(id int, time date);
  • 创建自定义存储过程:
CREATE OR REPLACE PROCEDURE PRC_JOB_1()
AS
N_NUM integer :=1;
BEGIN
FOR I IN 1..1000 LOOP
INSERT INTO test VALUES(I,SYSDATE);
END LOOP;
END;
/
  • 创建任务:
call dbms_job.submit('call public.prc_job_1(); ', sysdate, 'interval ''1 minute''', :a);
job
-----
1
(1 row)
  • 通过视图查看当前用户已创建的任务信息:
select job,dbname,start_date,last_date,this_date,next_date,broken,status,interval,failures,what from user_jobs;
job | dbname |     start_date      |         last_date          |         this_date          |      next_date      | broken | status |      interval       | failures |           what
-----+--------+---------------------+----------------------------+----------------------------+---------------------+--------+--------+---------------------+----------+---------------------------
1 | gaussdb   | 2017-07-18 11:38:03 | 2017-07-18 13:53:03.607838 | 2017-07-18 13:53:03.607838 | 2017-07-18 13:54:03 | n      | s      | interval '1 minute' |        0 | call public.prc_job_1();
(1 row)
  • 停止任务:
call dbms_job.broken(1,true);
broken
--------

(1 row)
  • 启动任务:
call dbms_job.broken(1,false);
broken
--------

(1 row)
  • 删除 JOB:
call dbms_job.remove(1);
remove
--------

(1 row)

四、GaussDB(DWS)模拟数据分析

① 准备工作

  • 使用华为云帐号,且在使用 GaussDB(DWS) 前检查帐号状态,帐号不能处于欠费或冻结状态。
  • 创建访问密钥(AK 和 SK):
    • 登录 GaussDB(DWS) 管理控制台,单击右上角用户名,在下拉菜单中单击“我的凭证”:

华为云原生之数据仓库服务GaussDB(DWS)的深度使用与应用实践

    • 在左侧导航树单击“访问密钥”,再单击“新增访问密钥”,在弹出的对话框中,输入登录密码和对应验证码,然后单击“确定”:

华为云原生之数据仓库服务GaussDB(DWS)的深度使用与应用实践

    • 在弹出的“下载确认”提示框中,单击“确定”后,密钥会直接保存到浏览器默认的下载文件夹中,打开下载下来的“credentials.csv”文件即可获取到访问密钥(AK 和 SK)。
  • 按照上文的流程,已成功创建集群,并已使用 Data Studio 连接集群。

② 导入样例数据

  • 创建数据库表:

华为云原生之数据仓库服务GaussDB(DWS)的深度使用与应用实践

  • 在 gaussdb 数据库中创建名字为 tpch 的 schema 和对应的数据表:
CREATE schema tpch; 
set current_schema = tpch;

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);
  • 创建外表,用于识别和关联 OBS 上的源数据:
CREATE schema tpchobs;
set current_schema='tpchobs';
drop FOREIGN table if exists region;
CREATE FOREIGN TABLE REGION
(
        like tpch.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;
CREATE FOREIGN TABLE NATION
(
        like tpch.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;
CREATE FOREIGN TABLE SUPPLIER
(
        like tpch.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;
CREATE FOREIGN TABLE CUSTOMER
(
        like tpch.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;
CREATE FOREIGN TABLE PART
(
        like tpch.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;
CREATE FOREIGN TABLE PARTSUPP
(
        like tpch.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;
CREATE FOREIGN TABLE ORDERS
(
        like tpch.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;
CREATE FOREIGN TABLE LINEITEM
(
        like tpch.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'
);
  • 将 OBS 外表的数据通过 insert 命令导入 GaussDB(DWS) 的数据库表中,数据库内核对应的操作为 OBS 数据高速并发导入 GaussDB(DWS) :
insert into tpch.lineitem select * from tpchobs.lineitem;
insert into tpch.part select * from tpchobs.part;
insert into tpch.partsupp select * from tpchobs.partsupp;
insert into tpch.customer select * from tpchobs.customer;
insert into tpch.supplier select * from tpchobs.supplier;
insert into tpch.nation select * from tpchobs.nation;
insert into tpch.region select * from tpchobs.region;
insert into tpch.orders select * from tpchobs.orders;

③ 数据分析

  • 在进行数据查询之前,请先执行“Analyze”命令生成与数据库表相关的统计信息,统计信息存储在系统表 PG_STATISTIC 中,执行计划生成器会使用这些统计数据,以生成最有效的查询执行计划。
  • 执行 TPCH-Q5 语句进行查询(带有分组、排序、聚集操作并存的多表连接查询操作),可以获得某地区供货商为公司带来的收入(收入按照 sum( l_extendedprice * (1 - l_discount)) 计算):
set current_schema='tpch';
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 >= '2022-01-01'::date
and o_orderdate < '2022-01-01'::date + interval '1 year'
group by
n_name
order by
revenue desc;
  • 执行 TPCH-Q16 语句进行查询(带有分组、排序、聚集、去重、NOT IN子查询操作并存的多表连接操作),可以获得能够以指定的贡献条件供应零件的供货商数量:
set current_schema='tpch';
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;
  • 执行 TPCH-Q17 语句进行查询(带有聚集、聚集子查询操作并存的两表连接操作),可以获得收入损失:
set current_schema='tpch';
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
);

五、GaussDB(DWS) 工作负载管理

  • 当有多个数据库用户同时在 GaussDB(DWS) 上执行 SQL 作业时,可能出现以下情况:
    • 一些复杂 SQL 可能会长时间占用集群资源,从而影响其他查询的性能。例如一组数据库用户不断提交复杂、耗时的查询,而另一组用户经常提交短查询,在这种情况下,短时查询可能不得不在队列中等待耗时查询完成。
    • 一些 SQL 由于数据倾斜、执行计划未调优等原因,占用过多内存空间,导致其他语句因申请不到内存而报错,或占用过多磁盘空间,导致磁盘满而触发集群只读,无法进行写入。
  • 为了提高系统整体吞吐量,避免坏 SQL 影响系统整体运行,可以使用 GaussDB(DWS)工作负载管理功能处理这类问题,例如,将经常提交复杂查询作业的数据库用户分为一类,为这类用户创建一个工作负载队列并给这个队列分配多一些的资源,之后将这类用户添加至这个队列中,那么这类用户所提交的复杂作业只能使用所创建队列拥有的资源;同时再创建一个占用资源较少的队列分配给执行短查询的用户使用,这样两种作业就能够同时执行互不影响。
  • 继续使用上文中”GaussDB(DWS)数据模拟分析“中,创建的集群并使用 Data Studio 连接集群连接集群的示例,来进行工作负载管理的分析。为有效进行资源管控,将报表分析和核心交易业务进行数据库用户分离,例如核心交易业务使用数据库用户 budget_config_user,报表分析业务使用数据库用户 report_user,针对交易用户和报表用户分别进行 CPU 资源和并发数控制以保障数据库稳定运行。
  • 结合报表分析业务的负载调研、日常监控和测试验证,50并发以内的复杂报表 SQL 不会引起服务器资源争抢,不会引起业务系统卡慢,配置报表用户可使用 20% 的CPU资源。结合核心交易业务的负载调研、日常监控和测试验证,100 并发以内的查询 SQL 不会对系统造成持续压力,配合交易用户可使用 60% 的 CPU 资源:
    • 报表用户资源配置(对应负载队列 queue_1):CPU=20%,内存=20%,存储=1024000MB,并发=20;
    • 交易用户资源配置(对应负载队列 queue_2):CPU=60%,内存=60%,存储=1024000MB,并发=200;
  • 设置单个语句最大内存使用量,超过使用量则报错退出,避免单个语句占用过多内存,异常规则中设置阻塞时间=1200S,执行所消耗时间 1800s,强制终止。
  • 首先创建核心交易用户 budget_config_user 和报表用户 report_user:
CREATE USER budget_config_user PASSWORD‘password’;
CREATE USER report_user PASSWORD‘password’;
  • 为测试需要,将 tpch 模式下所有表的所有权限授予两个用户:
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA tpch to budget_config_user,report_user;
  • 查看当前两个用户的资源分配情况:
SELECT * FROM PG_TOTAL_USER_RESOURCE_INFO where username in ('budget_config_user' , 'report_user');

华为云原生之数据仓库服务GaussDB(DWS)的深度使用与应用实践

  • 登录 GaussDB(DWS) 管理控制台,在集群列表中单击集群名称,切换至“工作负载管理”页签,单击工作负载队列旁的“+”符号添加队列,分别创建报表业务负载队列 queue_1 和核心交易负载队列 queue_2:

华为云原生之数据仓库服务GaussDB(DWS)的深度使用与应用实践
华为云原生之数据仓库服务GaussDB(DWS)的深度使用与应用实践

  • 修改异常规则:单击创建好的 queue_1 队列,在异常规则中,修改“阻塞时间”和“执行所消耗时间”分别为 1200s 和 1800s,然后保存(重复以上步骤,修改 queue_2):

华为云原生之数据仓库服务GaussDB(DWS)的深度使用与应用实践

  • 关联用户,点击“queue_1”队列 -> “关联用户”右侧的“添加”,勾选报表业务对应的用户 report_user,然后确定(重复以上步骤,将核心交易的用户 budget_config_user 添加入 queue_2 的队列中):

华为云原生之数据仓库服务GaussDB(DWS)的深度使用与应用实践
华为云原生之数据仓库服务GaussDB(DWS)的深度使用与应用实践

相关文章

暂无评论

暂无评论...