数据库运维
记录DBA学习成长历程

第7章:GBase 8c 高级语法

文章目录

1 课程目标

• 了解 GBase 8c 分布式版本高级语法涵义和使用方法,掌握并熟练使用。
• 存储引擎
• 分区表的各种组合 • 索引多样化
• 数据压缩
• 子事务

2 存储引擎

—2.1 目前支持

• USTORE,表示表支持Inplace-Update 存储引擎。
• ASTORE,表示表支持Append-Only 存储引擎。

—2.2 支持三种存储方法

• ROW,表示表的数据将以行式存储。
行存储适合于OLTP业务,适用于点查询或者增删操作比较多的场景。
• COLUMN,表示表的数据将以列式存储。
列存储适合于数据仓库业务,此类型的表上会做大量的汇聚计算,且涉及的列操作较少。
• MOT,表示表的数据将以内存的形式存储。
MOT 内存适用于高吞吐事务处理,性能瓶颈加速,消除中间层缓存,大规模流数据提取。

1:创建表时,指定 orientation 参数值为 row,创建行存表。
示例: create table test_astore_row(col text) with (orientation=row) ;
2:创建表时,指定 orientation 参数值为 column,创建列存表。
create table test_astore_column(col text) with (orientation=column);
3:创建表时,create foreign table ... server 为 mot_server时,创建内存表。
create foreign table test_astore_mot(col int) server mot_server ;
4:创建表时,指定 storage_type 参数值为 ustore,创建 ustore 表。
create table test_ustore(col text) with (storage_type=ustore);

当sql语句不做指定时,默认使用 astore 存储引擎,row 存储方法。

—2.3 示例

3 分区表

—3.1 介绍

GBase 8c 需要将数据按照一定规律分布到各个数据节点,目前支持 hash 分片。
在此基础上,分区表功能,支持二级分区,9种分区组合,interval 分区。即 分片+分区 功能。

—3.2 表分片

GBase 8c的数据分片策略:在创建表时,通过关键字distribute/replication 来设置表分片策略。
1:通过distribute by hash 创建 hash 分片表,将数据通过hash算法 均匀存储到每个数据节点。
CREATE TABLE t1_dis(c1 int, c2 int) DISTRIBUTE BY hash(c1);

2:通过distribute by replication 创建 复制表,每个数据节点都会存储一份数据。
CREATE TABLE t1_rep(c1 int, c2 int) DISTRIBUTE BY replication;
备注:在不指定时,默认使用hash分片,分布式键按照顺序为第一个满足hash算法的字段。

示例:

—3.3 hash 分片

hash 分片,hash 一级分区,hash-list,hash-hash,hash-range 二级分区
分区示例如下:

—3.4  range分区

hash 分片,range 一级分区,range-range,range-hash,range-list 二级分区。
分区示例如下:

—3.5 list分区

hash分片,list一级分区,list-list,list-range,list-hash 二级分区
分区示例如下:

—3.6 interval 分区

interval 分区:根据间隔自动创建分区,例如:1 day、1 month。(主备式)
CREATE TABLE sales(prod_id NUMBER(6),cust_id NUMBER,time_id DATE,channel_id
CHAR(1),promo_id NUMBER(6),quantity_sold NUMBER(3),amount_sold NUMBER(10,2))
PARTITION BY RANGE (time_id) INTERVAL('1 day')
( PARTITION p1 VALUES LESS THAN ('2019-02-01 00:00:00'),
PARTITION p2 VALUES LESS THAN ('2019-02-02 00:00:00')
);

—3.7 分区自动管理

分区自动管理:根据间隔自动创建分区,例如:1 day、1 month。(分布式)

语法:建表时增加 WITH, 或者通过 ALTER TABLE xxx SET (PERIOD='1 day')来实现。
(其中 PERIOD范围是 1 hour ~ 1 year)。通过ALTER TABLE xxx RESET (PERIOD)来关闭。

限制:仅支持RANGE分区的一级分区表 (其他分区类型,以及带有二级分区的表不支持)
效果:从当前命令时间(向下规约到hour)算起,连续增加能覆盖30个period时间范围 的分区,每个分区大小为period。如果现有分区在待新增的分区范围内,则跳过此新增分 区。且每隔period时间后再次执行此流程。

create table range_auto_1hour_tb01(id int,ip text,time timestamp)
with(PERIOD='1 hour') partition by range(time)( partition p1 values less than ('2022-11-23 14:00:00'));

示例:

4 索引类型

—4.1 介绍

GBase 8c 提供了多种索引类型:hash,B-tree,gist,gin。每一种索引类型使用了一种不同的算 法来适应不同类型的查询。

B-tree —— 适合所有的数据类型,支持排序,支持大于、小于、等于、大于或等于、小于或 等于的搜索。
hash —— 索引存储的是被索引字段VALUE的哈希值,只支持等值查询。
Gist(Generalized Search Tree) —— 即通用搜索树。可处理地理数据、图像,空间,树形图 等场景。
gin —— gin索引是“倒排索引”。应用领域是加速全文搜索。

默认情况下,create index 使用B-tree 索引并适合于大部分情况。

—4.2 B-tree 索引

btree索引常常用来进行例如大于、小于、等于这些操作。 通过语法:create index ... using btree(column) 。指定使用btree索引。

—4.3 gist 索引

地理数据、图像:如果我们想要查询在某个地方是否存在某一点,即判断地理位置的"包含“。
对于空间数据,GiST索引可以使用 R树,以支持相对位置运算符(位于左侧,右侧,包含等)。
对于树形图,R树可以支持相交或包含运算符。
通过语法:create index ... using gist(column) 。指定使用gist索引。

示例:

—4.4 gin 索引

当需要搜索多值类型内的VALUE时,适合多值类型,例如数组、全文检索、TOKEN。 (根据不同的类型,支持相交、包含、大于、在左边、在右边等搜索)。
通过语法:create index ... using gin(column) 。指定使用 gin 索引。

5 数据压缩

行存表 创建表时通过关键字 compresstype,可实现数据压缩,减少磁盘的占用。
create table test_row_compress(col text) with ( compresstype = 2, COMPRESS_LEVEL = 3);
◾ COMPRESSTYPE
行存表参数,设置行存表压缩算法。1代表pglz算法,2代表zstd算法,默认不压缩。(仅支持 ASTORE下的普通表)
取值范围:0~2,默认值为0。
◾ COMPRESS_LEVEL
行存表参数,设置行存表压缩算法等级,仅当COMPRESS_TYPE为2时生效。压缩等级越高,表 的压缩效果越好,表的访问速度越慢。(仅支持ASTORE下的普通表)
取值范围:-31~31,默认值为0。

示例:

列存表 创建表时通过关键字 compression,可实现数据压缩,减少磁盘的占用。
示例:create table test_compress(col text) with (orientation=column,compression=high);
◾ COMPRESSION:
指定表数据的压缩级别,它决定了表数据的压缩比以及压缩时间。一般来讲,压缩级别越高,压 缩比也越大,压缩时间也越长;反之亦然。实际压缩比取决于加载的表数据的分布特征。行存表 不支持压缩。
取值范围:
列存表的有效值为YES/NO/LOW/MIDDLE/HIGH,默认值为LOW。

示例:

6 子事务

子事务允许你回滚部分已经事务中完成的工作。可通过关键字 SAVEPOINT,EXCEPTION, Autonomous Transaction 启动子事务。

7 自治事务

自治事务(Autonomous Transaction),在主事务执行过程中新启的独立的事务。自治事 务的提交和回滚不会影响已提交的数据,同时 自治事务也不受主事务的影响。

自治事务在存储过程,函数和匿名块中定义, 用 PARAGMA AUTONOMOUS_TRANSACTION 关键字来 声明。

8 操作示例

/* ***************************************************** 以下命令为 linux 命令 ************************************************** */

--- su 命令切换到数据库用户 gbase,如果当前用户已为 gbase 用户,则忽略此条命令。
su - gbase

--- linux 命令:在安装节点(即执行gha_ctl start/stop 所在的节点) 执行 gs_guc 命令 修改数据库参数
gs_guc reload -Z coordinator -N all -I all -c "enable_incremental_checkpoint=off"
gs_guc reload -Z datanode -N all -I all -c "enable_incremental_checkpoint=off"
gs_guc reload -Z gtm -N all -I all -c "enable_incremental_checkpoint=off"

gs_guc reload -Z coordinator -N all -I all -c "enable_gbase_mot=on"
gs_guc reload -Z datanode -N all -I all -c "enable_gbase_mot=on"
gs_guc reload -Z gtm -N all -I all -c "enable_gbase_mot=on"


--- linux 命令:重启数据库加载数据库参数
gha_ctl stop all -l http://192.168.1.2:2379
gha_ctl start all -l http://192.168.1.2:2379

--- linux 命令:gsql 使用默认端口 连接数据库
gsql -d postgres -r -p 15432

/* ****************************************************** 以下都为sql命令 ******************************************************* */


--- gsql 连接成功后,将以下 sql 逐条在gsql中执行,进行验证。(若使用dbeaver工具,dbeaver 连接成功后,复制粘贴以下sql 执行进行验证)

---------存储引擎
---astore

drop table if exists test_astore_row ;
drop table if exists test_astore_column ;
drop foreign table if exists test_astore_mot ;
--- 创建 astore 行存表
create table test_astore_row(col text)  with (orientation=row) ;
--- 创建 astore 列存表
create table test_astore_column(col text) with (orientation=column);
--- 创建 astore 内存表
create foreign table test_astore_mot(col int) server mot_server ;

---ustore
drop table if exists test_ustore ;
create table test_ustore(col text)with(storage_type=ustore);


--- GBase 8c的数据分片策略:在创建表时,通过关键字distribute/replication 来设置表分片策略。

--- 1:通过distribute by hash 创建 hash 分片表,将数据通过hash算法 均匀存储到每个数据节点。创建hash分片

drop table if exists t1_dis ;
CREATE TABLE t1_dis(c1 int, c2 int)  DISTRIBUTE BY hash(c1);

--- 2:通过distribute by replication 创建 复制表,每个数据节点都会存储一份数据。

drop table if exists t1_rep ;
CREATE TABLE t1_rep(c1 int, c2 int)  DISTRIBUTE BY replication;

-- 分区表
-- 一级 hash 分区
drop table if exists mea_hash cascade;
create table mea_hash ( city_id int,logdate timestamp,id int )  partition by hash(id) ( partition p1 , partition p2 );

--二级分区 hash-list,hash-hash, hash-range
drop table if exists mea_hash_list cascade;
create table mea_hash_list ( city_id int,logdate timestamp,id int)  partition by hash(id) subpartition by list(city_id) ( partition p1  (subpartition p12 values (10),subpartition p13 values (20) ));

drop table if exists mea_hash_hash cascade;
create table mea_hash_hash ( city_id int,logdate timestamp,id int)  partition by hash(id) subpartition by hash(city_id) ( partition id_1  (subpartition p12 ,subpartition p13) );

drop table if exists mea_hash_range cascade;
create table mea_hash_range ( city_id int,logdate timestamp,id int)  partition by hash(id) subpartition by range(logdate) ( partition meas_y2021  (subpartition p12 values less than ('2021-02-04 12:00:00'),subpartition p13 values less than ('2021-02-04 20:00:00') ));
-- 一级 range 分区

drop table if exists mea_range cascade;
create table mea_range ( city_id int,logdate timestamp)  partition by range(logdate) ( partition meas_y2021 values less than  ('2021-01-01') );

--二级 range-range, range-hash,range-list
drop table if exists mea_range_range cascade;
create table mea_range_range ( city_id int,logdate timestamp,id int)  partition by range(logdate) subpartition  by range(id) ( partition meas_y2021 values less than ('2021-02-04 21:00:00') (subpartition p12 values less than (1),subpartition p13 values less than (10) ));

drop table if exists mea_range_hash cascade;
create table mea_range_hash ( city_id int,logdate timestamp,id int)  partition by range(logdate) subpartition by hash(city_id) ( partition id_1 values less than ('2021-02-01 01:00:00') (subpartition p12,subpartition p13) );
drop table if exists mea_range_list cascade;
create table mea_range_list ( city_id int,logdate timestamp,id int)  partition by range(logdate) subpartition by list(city_id) ( partition p1 values less than  ('2021-02-01 01:00:00') (subpartition p12 values (1),subpartition p13 values (20) ));

-- 一级 list 分区
drop table if exists mea_list cascade;
create table mea_list ( city_id int,logdate timestamp,id int )  partition by list(id) ( partition p1 values (1), partition p2 values (2) );
--期望支持.成功执行

-- 二级 list-list,list-range,list-hash 分区
drop table if exists mea_list_list cascade;
create table mea_list_list ( city_id int,logdate timestamp,id int)  partition by  list(id) subpartition by list(city_id) ( partition p1 values (1) (subpartition p12 values (10),subpartition p13 values (20) )); 

drop table if exists mea_list_range cascade;
create table mea_list_range ( city_id int,logdate timestamp,id int)  partition by  list(id) subpartition by range(logdate) ( partition meas_y2021 values ('202102') (subpartition p12 values less than ('2021-02-04 12:00:00'),subpartition p13 values less than ('2021-02-04 20:00:00') ));

drop table if exists mea_list_hash cascade;
create table mea_list_hash ( city_id int,logdate timestamp,id int)  partition by  list(id) subpartition by hash(city_id) ( partition id_1 values (2021) (subpartition p12,subpartition p13) );


------------数据库分区查看
with RECURSIVE temp_partition as( 
SELECT t1.oid, t1.relname, partstrategy, boundaries,t1.parttype FROM pg_partition t1, pg_class t2 WHERE t1.parentid = t2.oid AND t2.relname = 'mea_hash_hash' 
union
SELECT t1.oid, t1.relname, t1.partstrategy, t1.boundaries,t1.parttype FROM pg_partition t1 join temp_partition  t2 on t1.parentid = t2.oid where t2.parttype='p')
select t1.relname, t1.partstrategy, t1.boundaries,t1.parttype  from temp_partition t1;

--- 自动分区功能,请注意:创建分表时,子分区必须要有一个 大于当前时间 2小时的 分区。时间需按照实际时间 进行修改。
create table range_auto_1hour_tb01(id int,ip text,time timestamp) with(PERIOD='1 hour') partition by range(time)( partition p1 values less than ('2023-02-23 19:00'));

select * from dba_tab_partitions where table_name = 'RANGE_AUTO_1HOUR_TB01';
insert into range_auto_1hour_tb01 values(1,'12','2023-2-18 09:00:00');
insert into range_auto_1hour_tb01 values(2,'10','2023-2-18 10:00:00');
insert into range_auto_1hour_tb01 values(2,'10','2023-2-19 18:00:00');
insert into range_auto_1hour_tb01 values(2,'10','2023-2-19 19:00:00');


--多种索引
--hash 索引
create table rw_split(col int,name text);
insert into rw_split select generate_series(1,50000), md5(random()::text)::text;

create index rw_split_col_hash on rw_split using hash(col);
explain select * from rw_split where col =2;

-----------------btree 索引

drop index rw_split_col_hash;

create index rw_split_col_btree on rw_split using btree(col);
explain select * from rw_split where col =2;

---------------gist 索引

drop table if exists t_gist;
create table t_gist(id int,p point);
insert into t_gist select generate_series(1,10000),point(round((random()*1000)::numeric,2),round((random()*1000)::numeric,2));
select * from t_gist limit 2;
create index on t_gist using gist(p);
explain (analyze,buffers) select * from t_gist where circle '((100,100) 1)' @> p order by p <-> '(100,100)' limit 10; ---在 100,100 点,半径10 以内的点。


---------------gin索引
drop table if exists t_gin;
create table t_gin(doc text, doc_tsv tsvector);
insert into t_gin(doc) values
  ('Can a sheet slitter slit sheets?'),
  ('How many sheets could a sheet slitter slit?'),
  ('I slit a sheet, a sheet I slit.'),
  ('Upon a slitted sheet I sit.'),
  ('Whoever slit the sheets is a good sheet slitter.'),
  ('I am a sheet slitter.'),
  ('I slit sheets.'),
  ('I am the sleekest sheet slitter that ever slit sheets.'),
  ('She slits the sheet she sits on.');
update t_gin set doc_tsv = to_tsvector(doc);
create index on t_gin using gin(doc_tsv);

--- 为了效果,手动关闭顺序扫描。
set enable_seqscan=off;

explain(costs off) select doc from t_gin where doc_tsv @@ to_tsquery('many & slitter');

--------------表达式索引

create table test_expression(col int, name varchar(64));

insert into test_expression select 1,'ASDD';
insert into test_expression select 2,'ASDD';
insert into test_expression select 3,'AS';
insert into test_expression select 4,'ASsda';
insert into test_expression select 5,'ASdssa';
insert into test_expression select 6,'Asds';
insert into test_expression select 7,'Assa';
insert into test_expression select 8,'as';


explain select * from test_expression where lower(name) ='as';

create index on test_expression (name);
create index test_expression_lower on test_expression (lower(name));

explain select * from test_expression where lower(name) ='as';

-----------数据压缩

---- 行存压缩
drop table  if exists test_row_compress;
create table test_row_compress(col text);
insert into test_row_compress select md5(random()::text) from generate_series(1,1000000);
select * from pg_size_pretty(pg_catalog.pg_table_size('test_row_compress'));

drop table  if exists test_row_compress;
create table test_row_compress(col text) with (compresstype = 2,compress_level= 3);
insert into test_row_compress select md5(random()::text) from generate_series(1,1000000);
select * from pg_size_pretty(pg_catalog.pg_table_size('test_row_compress'));

---- 列存压缩
drop table test_column_compress;
create table test_column_compress(col text) with (orientation=column,compression=no);
insert into test_column_compress select md5(random()::text) from generate_series(1,1000000);
select * from pg_size_pretty(pg_catalog.pg_table_size('test_column_compress'));

drop table test_column_compress;
create table test_column_compress(col text) with (orientation=column,compression=high);
insert into test_column_compress select md5(random()::text) from generate_series(1,1000000);
select * from pg_size_pretty(pg_catalog.pg_table_size('test_column_compress'));


----------------------子事务
-----自治事务

create table t2(a int,b int); insert into t2 values(1,2); select * from t2;

create or replace procedure autonomus_4(a int ,b int) as
declare
    num3 int =a; num4 int =b;
    pragma autonomous_transaction;
begin insert into t2 values (num3,num4); end;
/

create or replace procedure autonomus_5(a int ,b int) as
declare
begin insert into t2 values (444,55);autonomus_4(a,b);rollback; end;
/

select autonomus_5(11,22);
select * from t2;
-----------savepoint

--设置保存点
--创建表
drop table if exists savepoint_test;
create table savepoint_test(a int primary key,b int) ;
--开始事务
start transaction;
--插入数据
insert into savepoint_test values(1,2);
--创建保存点
savepoint test_savepoint;
--插入数据
insert into savepoint_test values(2,2);
--查看表中数据
select * from savepoint_test;
--回滚保存点
rollback to savepoint test_savepoint;
--查看表中数据(只能查到(1,1),(2,2)被回滚)
select * from savepoint_test;
--插入数据
insert into savepoint_test values(3,3);
--提交事务
commit;
--查看表中数据(=能查到(1,1)、(3,3),(2,2)被回滚)
select * from savepoint_test;
--删除测试表savepoint_test
drop table savepoint_test;

--------exception

create type type_test as (a int,b int);
create or replace procedure p1
as
c int;
begin
    select a into c from type_test;
exception
    when others then 
    raise 'NULL' ;
end;
/
call p1();

 

赞(0)
MySQL学习笔记 » 第7章:GBase 8c 高级语法