华为云用户手册

  • 对一级分区表删除分区 使用ALTER TABLE DROP PARTITION可以删除指定分区表的任何一个分区,这个行为可以作用在范围分区表、间隔分区表、列表分区表上。 例如,通过指定分区名删除范围分区表range_sales的分区date_202005,并更新Global索引。 ALTER TABLE range_sales DROP PARTITION date_202005 UPDATE GLOBAL INDEX; 或者,通过指定分区值来删除范围分区表range_sales中'2020-05-08'所对应的分区。由于不带UPDATE GLOBAL INDEX子句,执行该命令后Global索引会失效。 ALTER TABLE range_sales DROP PARTITION FOR ('2020-05-08'); 当分区表只有一个分区时,不支持通过ALTER TABLE DROP PARTITION命令删除分区。 当分区表为哈希分区表时,不支持通过ALTER TABLE DROP PARTITION命令删除分区。 父主题: 删除分区
  • 分区自动扩展 分区的自动扩展功能是分区表的一种能力增强。当DML业务(INSERT、UPDATE、UPSERT、MERGE INTO、COPY)新增数据无法匹配到已有的任一分区时,会自动创建一个新的分区。此外,以partition/subpartition for partition_value的方式创建分类索引时,若指定的分区不存在,也会自动创建一个新的分区。当前支持范围分区自动扩展和列表分区自动扩展。 范围分区自动扩展 列表分区自动扩展 开启/关闭分区自动扩展 自动扩展分区的创建策略 父主题: 分区表
  • 功能描述 数据库在执行DML的时候,存储引擎会生成对应的DML日志,用于进行恢复,对这些DML日志进行解码,即可还原对应的DML语句,生成逻辑日志。而对于DDL语句,数据库并不记录DDL原语句的日志,而是记录DDL语句涉及的系统表的DML日志。DDL种类多样、语法复杂,逻辑复制要支持DDL语句,通过这些系统表的DML日志来解码原DDL语句是非常困难的。新增DDL日志记录原DDL信息,并在解码时通过DDL日志可以得到DDL原语句。 在DDL语句执行过程中,SQL引擎解析器会对原语句进行语法、词法解析,并生成解析树(不同的DDL语法会生成不同类型的解析树,解析树中包含DDL语句的全部信息)。随后,执行器通过这些信息执行对应操作,生成、修改对应元信息。 本文通过新增DDL日志的方式,来支持逻辑解码DDL,其内容由解析器结果(解析树)以及执行器结果生成,并在执行器执行完成后生成该日志。 从语法树反解析出DDL,DDL反解析能够将DDL命令转换为JSON格式的语句,并提供必要的信息在目标位置重建DDL命令。与原始DDL命令字符串相比,使用DDL反解析的好处包括: 解析出来的每个数据库对象都带有Schema,因此如果使用不同的search_path,也不会有歧义。 结构化的JSON和格式化的输出能支持异构数据库。如果用户使用的是不同的数据库版本,并且存在某些DDL语法差异,需要在应用之前解决这些差异。 反解析输出的结果是规范化后的形式,结果与用户输入等价,不保证完全相同,例如: 示例1:在函数体中没有单引号'时,函数体的分隔符$$会被解析为单引号'。 原始SQL语句: CREATE FUNCTION func(a INT) RETURNS INT AS $$ BEGIN a:= a+1; CREATE TABLE test(col1 INT); INSERT INTO test VALUES(1); DROP TABLE test; RETURN a; END; $$ LANGUAGE plpgsql; 反解析结果: CREATE FUNCTION public.func ( IN a pg_catalog.int4 ) RETURNS pg_catalog.int4 LANGUAGE plpgsql VOLATILE CALLED ON NULL INPUT SECURITY INVOKER COST 100 AS ' BEGIN a:= a+1; CREATE TABLE test(col1 INT); INSERT INTO test VALUES(1); DROP TABLE test; RETURN a; END; '; 示例2:“CREATE MATERIALIZED VIEW v46_4 AS SELECT a, b FROM t46 ORDER BY a OFFSET 10 ROWS FETCH NEXT 3 ROWS ONLY”会被反解析为“CREATE MATERIALIZED VIEW public.v46_4 AS SELECT a, b FROM public.t46 ORDER BY a OFFSET 10 LIMIT 3”;。 示例3:“ALTER INDEX "Alter_Index_Index" REBUILD PARTITION "CA_ADDRESS_SK_index2"”会被反解析为“REINDEX INDEX public."Alter_Index_Index" PARTITION "CA_ADDRESS_SK_index2"”。 示例4:创建/修改范围分区表,START END语法格式均解码转化为LESS THAN语句: gaussdb=# CREATE TABLE test_create_table_partition2 (c1 INT, c2 INT) PARTITION BY RANGE (c2) ( PARTITION p1 START(1) END(1000) EVERY(200) , PARTITION p2 END(2000), PARTITION p3 START(2000) END(2500), PARTITION p4 START(2500), PARTITION p5 START(3000) END(5000) EVERY(1000) );
  • 解码格式 JSON形式 对于输入的DDL语句,SQL引擎解析器会通过语法、词法分析将其分解为解析树,解析树节点中包含了DDL的全部信息,并且执行器会根据解析树内容,执行系统元信息的修改。在执行器执行完成之后,便可以获取到DDL操作数据对象的search_path。本特性在执行器执行成功之后,对解析树信息以及执行器结果进行反解析,以还原出DDL原语句的全部信息。反解析的方式可以分解整个DDL语句,以方便输出JSON形式的DDL,用以适配异构数据库场景。 CREATE TABLE语句在经过词法、语法分析之后,得到对应的CreateStmt解析树节点,节点中包含了表信息、列信息、分布式信息(DistributeBy结构体)、分区信息(PartitionState结构)等。通过反解析后,可输出的JSON形式如下: {"JDDL":{"fmt":"CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D %{table_elements}s %{with_clause}s %{compression}s","identity":{"object_name":"test_create_table_a","schema_name":"public"},"compression":"NOCOMPRESS","persistence":"","with_clause":{"fmt":"WITH (%{with:, }s)","with":[{"fmt":"%{label}s = %{value}L","label":{"fmt":"%{label}I","label":"orientation"},"value":"row"},{"fmt":"%{label}s = %{value}L","label":{"fmt":"%{label}I","label":"compression"},"value":"no"}]},"if_not_exists":"","table_elements":{"fmt":"(%{elements:, }s)","elements":[{"fmt":"%{name}I %{column_type}T","name":"a","column_type":{"typmod":"","typarray":false,"type_name":"int4","schema_name":"pg_catalog"}}]}}} 可以看到,JSON形式中包含对象的search_path,其中的identity键标识schema为public,表名为test_create_table_a,其中%{persistence}s对应的字段如下,此SQL语句不含此字段所以为空。 [ [ GLOBAL | LOCAL ] [ TEMPORARY | TEMP ] | UNLOGGED ] %{if_not_exists}s对应SQL语句中的字段,不含此字段所以为空: [ IF NOT EXISTS ] %{identity}D对应SQL语句中的字段: table_name %{table_elements}s对应SQL语句中的字段: (column_name data_type) %{with_clause}s对应SQL语句中的字段: [ WITH ( {storage_parameter = value} [, ... ] ) ] %{compression}s对应SQL语句中的字段: [ COMPRESS | NOCOMPRESS ] SQL形式 输出的SQL形式(文本方式)为: {"TDDL":"CREATE TABLE public.test_create_table_a (a pg_catalog.int4) WITH (orientation = 'row', compression = 'no') NOCOMPRESS"} 其中语句中也包含Schema名称。
  • 接口设计 新增控制参数 新增逻辑解码控制参数,用于控制DDL的反解析流程以及输出形式。可通过pg_recvlogical -o或者pg_logical_slot_peek_changes开启。 enable-ddl-decoding:默认false,不开启DDL语句的逻辑解码;值为true时,开启DDL语句的逻辑解码。 enable-ddl-json-format:默认false,传送TEXT格式的DDL反解析结果;值为true时,传送JSON格式的DDL反解析结果。 新增GUC参数 enable_logical_replication_ddl:默认为ON,ON状态下,逻辑复制可支持DDL,否则,不支持DDL。只有当ON状态下,才会对DDL执行结果进行反解析,并生成DDL的WAL日志。否则,不反解析也不生成WAL日志。 enable_logical_replication_ddl的开关日志,以证明是否是用户修改了该参数导致逻辑解码不支持DDL。 新增日志 新增DDL日志xl_logical_ddl_message,其类型为RM_LOGICALDDLMSG_ID。其定义如下: 名称 类型 意义 db_id Oid 数据库ID rel_id Oid 表ID csn CommitSeqNo CSN快照 cid CommandId Command ID tag_type NodeTag DDL类型 message_size Size 日志内容长度 filter_message_size Size 日志中白名单过滤信息长度 message char * DDL内容
  • PCR UBTree增删改查 Insert操作:操作与RCR UBTree基本一致,区别是:插入前需要先申请TD和写入Undo。 Delete操作:操作与RCR UBTree基本一致,区别是:删除前需要先申请TD和写入Undo。 Update操作:操作与RCR UBTree无区别,均转换为一条Delete操作和和一条Insert操作。 Scan操作:操作与RCR UBTree基本一致,区别是:查询操作需要将页面复制一个CR页面出来,将CR页面回滚到扫描快照可见的状态,从而整个页面的元组对于快照都是可见版本。 父主题: PCR UBTree
  • 事务提交 针对隐式事务和显式事务,其提交策略如下所示: 隐式事务。单条DML/DDL语句自动触发隐式事务,这种事务没有显式的事务块控制语句(START TRANSACTION/BEGIN/COMMIT/END),DML语句结束后自动提交。 显式事务。显式事务由显式的START TRANSACTION/BEGIN语句控制事务的开始,由COMMIT/END语句控制事务的提交。 子事务必须存在于显式事务或存储过程中,由SAVEPOINT语句控制子事务开始,由RELEASE SAVEPOINT语句控制子事务结束。如果一个事务在提交时还存在未释放的子事务,该事务提交前会先执行子事务的提交,所有子事务提交完毕后才会进行父事务的提交。 Ustore支持读已提交隔离级别。语句在执行开始时,获取当前系统的CSN作为当前语句的查询CSN。整个语句的可见结果由语句开始那一刻决定,不受后续其他事务修改影响。Ustore中read committed默认是保持一致性读的。Ustore也支持标准的2PC事务。 父主题: Ustore事务模型
  • 表分区技术 表分区技术(Table-Partitioning)通过将非常大的表或者索引从逻辑上切分为更小、更易管理的逻辑单元(分区),能够让对用户对表查询、变更等语句操作具备更小的影响范围,能够让用户通过分区键(Partition Key)快速定位到数据所在的分区,从而避免在数据库中对大表的全量扫描,能够在不同的分区上并发进行DDL、DML操作。从用户使用的角度来看,表分区技术主要有以下三个方面能力: 提升大容量数据场景查询效率:由于表内数据按照分区键进行逻辑分区,查询结果可以通过访问分区的子集而不是整个表来实现。这种分区剪枝技术可以提供数量级的性能增益。 降低运维与查询的并发操作影响:降低DML语句、DDL语句并发场景的相互影响,在对一些大数据量以时间维度进行分区的场景下会明显受益。例如,新数据分区进行入库、实时点查操作,老数据分区进行数据清洗、分区合并等运维性质操作。 提供大容量场景下灵活的数据运维管理方式:由于分区表从物理上对不同分区的数据做了表文件层面的隔离,每个分区可以具有单独的物理属性,如启用或禁用压缩、物理存储设置和表空间。同时它支持数据管理操作,如数据加载、索引创建和重建,以及分区级别的备份和恢复,而不是对整个表进行操作,从而减少了操作时间。 父主题: 大容量数据库
  • 交换分区 用户可以使用交换分区的命令来将分区与普通表的数据进行交换。交换分区可以快速将数据导入/导出分区表,实现数据高效加载的目的。在业务迁移的场景,使用交换分区比常规导入会快很多。交换分区可以通过指定分区名或者分区值来进行。 执行交换分区命令会使得Global索引失效,可以通过UPDATE GLOBAL INDEX子句来同步更新Global索引,或者用户自行重建Global索引。 执行交换分区时,可以申明WITH/WITHOUT VALIDATION,表明是否校验普通表数据满足目标分区的分区键约束规则(默认校验)。数据校验活动开销较大,如果能确保交换的数据属于目标分区,可以申明WITHOUT VALIDATION来提高交换性能。 可以申明WITH VALIDATION VERBOSE,此时数据库会校验普通表的每一行,将不满足目标分区的分区键约束规则的数据,插入到分区表的其他分区中,最后再进行普通表与目标分区的交换。 例如,给出如下分区定义和普通表exchange_sales的数据分布,并将分区DATE_202001和普通表exchange_sales做交换,则根据申明子句的不同,存在以下三种行为: 申明WITHOUT VALIDATION,数据全部交换到分区DATE_202001中,由于'2020-02-03', '2020-04-08'不满足分区DATE_202001的范围约束,后续业务可能会出现异常。 申明WITH VALIDATION,由于'2020-02-03', '2020-04-08'不满足分区DATE_202001的范围约束,数据库给出相应的报错。 申明WITH VALIDATION VERBOSE,数据库会将'2020-02-03'插入分区DATE_202002,将'2020-04-08'插入分区DATE_202004,再将剩下的数据交换到分区DATE_202001中。 --分区定义 PARTITION DATE_202001 VALUES LESS THAN ('2020-02-01'), PARTITION DATE_202002 VALUES LESS THAN ('2020-03-01'), PARTITION DATE_202003 VALUES LESS THAN ('2020-04-01'), PARTITION DATE_202004 VALUES LESS THAN ('2020-05-01') -- exchange_sales的数据分布 ('2020-01-15', '2020-01-17', '2020-01-23', '2020-02-03', '2020-04-08') 如果交换的数据不完全属于目标分区,请不要申明WITHOUT VALIDATION交换分区,否则会破坏分区约束规则,导致分区表后续DML业务结果异常。 进行交换的普通表和分区必须满足如下条件: 普通表和分区的列数目相同,对应列的信息严格一致。 普通表和分区的表压缩信息严格一致。 普通表索引和分区Local索引个数相同,且对应索引的信息严格一致。 普通表和分区的表约束个数相同,且对应表约束的信息严格一致。 普通表不可以是临时表。 普通表和分区表上不可以有动态数据脱敏,行访问控制约束。 对一级分区表交换分区 对二级分区表交换二级分区 父主题: 分区表运维管理
  • 向二级分区表新增二级分区 使用ALTER TABLE MODIFY PARTITION ADD SUBPARTITION可以在二级分区表中新增一个二级分区,这个行为可以作用在二级分区策略为RANGE或者LIST的情况。 例如,对二级分区表range_list_sales的date_202004新增一个二级分区。 ALTER TABLE range_list_sales MODIFY PARTITION date_202004 ADD SUBPARTITION date_202004_channel5 VALUES ('X') TABLESPACE tb2; 当二级分区表的二级分区策略为HASH时,不支持通过ALTER TABLE MODIFY PARTITION ADD SUBPARTITION命令新增二级分区。 父主题: 新增分区
  • 约束 分区表索引分为LOCAL索引与GLOBAL索引:LOCAL索引与某个具体分区绑定,而GLOBAL索引则对应整个分区表。 唯一约束和主键约束的约束键包含所有分区键则创建LOCAL索引,否则创建GLOBAL索引。 在创建LOCAL索引时,可以通过FOR { partition_name | ( partition_value [, ...] ) }子句,指定在单个分区上创建LOCAL索引,此类索引在其他分区上不生效,后续新增的分区也不会自动创建该索引。需要注意的是,当前仅静态剪枝到单个分区的计划支持生成分类索引的查询路径。
  • 示例 创建表 gaussdb=# CREATE TABLE 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) ) 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; 创建索引 创建分区表LOCAL索引tpcds_web_returns_p2_index1,不指定索引分区的名称。 gaussdb=# CREATE INDEX tpcds_web_returns_p2_index1 ON web_returns_p2 (ca_address_id) LOCAL; 当结果显示为如下信息,则表示创建成功。 CREATE INDEX 创建分区表LOCAL索引tpcds_web_returns_p2_index2,并指定索引分区的名称。 gaussdb=# CREATE TABLESPACE example2 LOCATION '/home/omm/example2'; CREATE TABLESPACE example3 LOCATION '/home/omm/example3'; CREATE TABLESPACE example4 LOCATION '/home/omm/example4'; gaussdb=# CREATE INDEX tpcds_web_returns_p2_index2 ON 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; 当结果显示为如下信息,则表示创建成功。 CREATE INDEX 创建分区表GLOBAL索引tpcds_web_returns_p2_global_index。 gaussdb=# CREATE INDEX tpcds_web_returns_p2_global_index ON web_returns_p2 (ca_street_number) GLOBAL; 当结果显示为如下信息,则表示创建成功。 CREATE INDEX 创建分类分区索引 指定分区名: gaussdb=# CREATE INDEX tpcds_web_returns_for_p1 ON web_returns_p2 (ca_address_id) LOCAL(partition ind_part for p1); 指定分区键的值: gaussdb=# CREATE INDEX tpcds_web_returns_for_p2 ON web_returns_p2 (ca_address_id) LOCAL(partition ind_part for (5000)); 当结果显示为如下信息,则表示创建成功。 CREATE INDEX 修改索引分区的表空间 修改索引分区web_returns_p2_P2_index的表空间为example1。 gaussdb=# ALTER INDEX tpcds_web_returns_p2_index2 MOVE PARTITION web_returns_p2_P2_index TABLESPACE example1; 当结果显示为如下信息,则表示修改成功。 ALTER INDEX 修改索引分区web_returns_p2_P3_index的表空间为example2。 gaussdb=# ALTER INDEX tpcds_web_returns_p2_index2 MOVE PARTITION web_returns_p2_P3_index TABLESPACE example2; 当结果显示为如下信息,则表示修改成功。 ALTER INDEX 重命名索引分区 执行如下命令对索引分区web_returns_p2_P8_index重命名web_returns_p2_P8_index_new。 gaussdb=# ALTER INDEX tpcds_web_returns_p2_index2 RENAME PARTITION web_returns_p2_P8_index TO web_returns_p2_P8_index_new; 当结果显示为如下信息,则表示重命名成功。 ALTER INDEX 查询索引 执行如下命令查询系统和用户定义的所有索引。 gaussdb=# SELECT RELNAME FROM PG_CLASS WHERE RELKIND='i' or RELKIND='I'; 执行如下命令查询指定索引的信息。 gaussdb=# \di+ tpcds_web_returns_p2_index2 删除索引 gaussdb=# DROP INDEX tpcds_web_returns_p2_index1; 当结果显示为如下信息,则表示删除成功。 DROP INDEX 清理示例 gaussdb=# DROP TABLE web_returns_p2;
  • 索引重建/不可用 使用ALTER INDEX可以设置索引是否可用。 例如,假设分区表range_ sales上存在索引range_sales_idx,可以通过如下命令设置其不可用。 ALTER INDEX range_sales_idx UNUSABLE; 可以通过如下命令重建索引range_sales_idx。 ALTER INDEX range_sales_idx REBUILD; 父主题: 分区表索引重建/不可用
  • GaussDB内核503版本 - Ustore适配分布式/并行查询/Global Temp Table/Vacuum full/列约束DEFERRABLE以及INITIALLY DEFERRED。 - Ustore增加在线重建索引。 - Ustore增加增强版本B-tree空页面估算,提升优化器代价估算准确度。 - Ustore增加存储引擎可靠性验证框架,Dignose Page/Page Verify。 - Ustore增强存储引擎相关的解析/检测/修复视图。 - Ustore增强基于WAL日志的定位能力,新增gs_redo_upage系统视图,支持对单页面的不断重放,获取并打印该页面的任何一个历史版本,加速页面损坏类问题的定位。 - Ustore扩展事务槽TD物理格式,为事务内空间复用做好铺垫。 - Ustore增加在线创建索引。 - Ustore适配闪回功能(for Ustore)/极致RTO。 父主题: 存储引擎更新说明
  • 对二级分区表删除二级分区 使用ALTER TABLE DROP SUBPARTITION可以删除二级分区表的一个二级分区,这个行为可以作用在二级分区策略为RANGE或者LIST的情况。 例如,通过指定分区名删除二级分区表range_list_sales的二级分区date_202005_channel1,并更新Global索引。 ALTER TABLE range_list_sales DROP SUBPARTITION date_202005_channel1 UPDATE GLOBAL INDEX; 或者,通过指定分区值来删除二级分区表range_list_sales中('2020-05-08', '0')所对应的二级分区。由于不带UPDATE GLOBAL INDEX子句,执行该命令后Global索引会失效。 ALTER TABLE range_list_sales DROP SUBPARTITION FOR ('2020-05-08', '0'); 当二级分区表所删除的目标分区只有一个二级分区时,不支持通过ALTER TABLE DROP SUBPARTITION命令删除二级分区。 当二级分区表的二级分区策略为HASH时,不支持通过ALTER TABLE DROP SUBPARTITION命令删除二级分区。 父主题: 删除分区
  • 常规锁设计 分区表通过表锁+分区锁两重设计,在表和分区上分别施加8个不同级别的常规锁,来保证DQL、DML、DDL并发过程中的合理行为控制。下表给出了不同级别锁的互斥行为,标记为√的两种常规锁互不阻塞,可以并行。 表1 常规锁行为 - ACCESS_SHARE ROW_SHARE ROW_EXCLUSIVE SHARE_UPDATE_EXCLUSIVE SHARE SHARE_ROW_EXCLUSIVE EXCLUSIVE ACCESS_EXCLUSIVE ACCESS_SHARE √ √ √ √ √ √ √ × ROW_SHARE √ √ √ √ √ √ × × ROW_EXCLUSIVE √ √ √ √ × × × × SHARE_UPDATE_EXCLUSIVE √ √ √ × × × × × SHARE √ √ × × √ × × × SHARE_ROW_EXCLUSIVE √ √ × × × × × × EXCLUSIVE √ × × × × × × × ACCESS_EXCLUSIVE × × × × × × × × 分区表的不同业务最终都是作用于目标分区上,数据库会给分区表和目标分区施加不同级别的表锁+分区锁,来控制并发行为。下表给出了不同业务的锁粒度控制。其中数字1~8代表上表给出的8种级别常规锁。 表2 分区表业务锁粒度 业务模型 一级分区表锁级别(表锁+分区锁) 二级分区表锁级别(表锁+一级分区锁+二级分区锁) SELECT 1-1 1-1-1 SELECT FOR UPDATE 2-2 2-2-2 DML业务,包括INSERT、UPDATE、DELETE、UPSERT、MERGE INTO、COPY 3-3 3-3-3 分区DDL,包括ADD、DROP、EXCHANGE、TRUNCATE、SPLIT、MERGE、MOVE、RENAME;打开/关闭分区自动扩展 4-8 4-8-8(作用二级分区表的一级分区) 4-4-8 (作用二级分区表的二级分区) CREATE INDEX(非分类索引)、REBUILD INDEX 5-5 5-5-5 CREATE INDEX(分类索引) 3-5 3-3-5 REBUILD INDEX PARTITION 1-5 1-5-5 ANALYZE、VACUUM 4-4 4-4-4 其他分区表DDL 8-8 8-8-8 父主题: 分区并发控制
  • 删除分区 用户可以使用删除分区的命令来移除不需要的分区。删除分区可以通过指定分区名或者分区值来进行。 删除分区不能作用于HASH分区上。 执行删除分区命令会使得Global索引失效,可以通过UPDATE GLOBAL INDEX子句来同步更新Global索引,或者用户自行重建Global索引。 删除分区时,如果该分区上带有仅属于当前分区的分类索引时,则会级联删除分类索引。 对一级分区表删除分区 对二级分区表删除一级分区 对二级分区表删除二级分区 父主题: 分区表运维管理
  • 对二级分区表删除一级分区 使用ALTER TABLE DROP PARTITION可以删除二级分区表的一个一级分区,这个行为可以作用在一级分区策略为RANGE或者LIST的情况。数据库会将这个一级分区,以及一级分区下的所有二级分区都删除。 例如,通过指定分区名删除二级分区表range_list_sales的一级分区date_202005,并更新Global索引。 ALTER TABLE range_list_sales DROP PARTITION date_202005 UPDATE GLOBAL INDEX; 或者,通过指定分区值来删除二级分区表range_list_sales中('2020-05-08')所对应的一级分区。由于不带UPDATE GLOBAL INDEX子句,执行该命令后Global索引会失效。 ALTER TABLE range_list_sales DROP PARTITION FOR ('2020-05-08'); 当二级分区表只有一个一级分区时,不支持通过ALTER TABLE DROP PARTITION命令删除一级分区。 当二级分区表的一级分区策略为HASH时,不支持通过ALTER TABLE DROP PARTITION命令删除一级分区。 父主题: 删除分区
  • 对一级分区表交换分区 使用ALTER TABLE EXCHANGE PARTITION可以对一级分区表交换分区。 例如,通过指定分区名将范围分区表range_sales的分区date_202001和普通表exchange_sales进行交换,不进行分区键校验,并更新Global索引。 ALTER TABLE range_sales EXCHANGE PARTITION (date_202001) WITH TABLE exchange_sales WITHOUT VALIDATION UPDATE GLOBAL INDEX; 或者,通过指定分区值将范围分区表range_sales中'2020-01-08'所对应的分区和普通表exchange_sales进行交换,进行分区校验并将不满足目标分区约束的数据插入到分区表的其他分区中。由于不带UPDATE GLOBAL INDEX子句,执行该命令后Global索引会失效。 ALTER TABLE range_sales EXCHANGE PARTITION FOR ('2020-01-08') WITH TABLE exchange_sales WITH VALIDATION VERBOSE; 父主题: 交换分区
  • 不支持场景 物化视图中不支持多表Join连接计划以及subquery计划。 除少部分ALTER操作外,不支持对物化视图中基表执行绝大多数DDL操作。 物化视图不支持增删改操作,只支持查询语句。 不支持用临时表/hashbucket/unlog/分区表创建物化视图。 不支持物化视图嵌套创建(即物化视图上创建物化视图)。 不支持UNLOGGED类型的物化视图,不支持WITH语法。 Ustore引擎不支持增量物化视图的创建和使用。
  • 对一级分区表重命名分区 使用ALTER TABLE RENAME PARTITION可以对一级分区表重命名分区。 例如,通过指定分区名将范围分区表range_sales的分区date_202001重命名。 ALTER TABLE range_sales RENAME PARTITION date_202001 TO date_202001_new; 或者,通过指定分区值将列表分区表list_sales中'0'所对应的分区重命名。 ALTER TABLE list_sales RENAME PARTITION FOR ('0') TO channel_new; 父主题: 重命名分区
  • 分区表介绍 分区表(Partitioned Table)指在单节点内对表数据内容按照分区键以及围绕分区键的分区策略对表进行逻辑切分。从数据分区的角度来看是一种水平分区(horizontal partition)策略方式。分区表增强了数据库应用程序的性能、可管理性和可用性,并有助于降低存储大量数据的总体拥有成本。分区允许将表、索引和索引组织的表细分为更小的部分,使这些数据库对象能够在更精细的粒度级别上进行管理和访问。GaussDB提供了丰富的分区策略和扩展,以满足不同业务场景的需求。由于分区策略的实现完全由数据库内部实现,对用户是完全透明的,因此它几乎可以在实施分区表优化策略以后做平滑迁移,无需潜在耗费人力物力的应用程序更改。本章围绕GaussDB分区表的基本概念从以下几个方面展开介绍: 分区表基本概念:从表分区的基本概念出发,介绍分区表的catalog存储方式以及内部对应原理。 分区策略:从分区表所支持的基本类型出发,介绍各种分区模式下对应的特性以及能够达到的优化特点和效果。 基本概念 分区策略 分区基本使用 父主题: 分区表
  • 示例 -- 修改表的默认类型 gaussdb=# set enable_default_ustore_table=off; --准备数据。 gaussdb=# CREATE TABLE t1(c1 int, c2 int); gaussdb=# INSERT INTO t1 VALUES(1, 1); gaussdb=# INSERT INTO t1 VALUES(2, 2); --创建全量物化视图。 gaussdb=# CREATE MATERIALIZED VIEW mv AS select count(*) from t1; CREATE MATERIALIZED VIEW --查询物化视图结果。 gaussdb=# SELECT * FROM mv; count ------- 2 (1 row) --向物化视图中基表插入数据。 gaussdb=# INSERT INTO t1 VALUES(3, 3); INSERT 0 1 --对全量物化视图做全量刷新。 gaussdb=# REFRESH MATERIALIZED VIEW mv; REFRESH MATERIALIZED VIEW --查询物化视图结果。 gaussdb=# SELECT * FROM mv; count ------- 3 (1 row) --删除物化视图,删除表。 gaussdb=# DROP MATERIALIZED VIEW mv; DROP MATERIALIZED VIEW gaussdb=# DROP TABLE t1; DROP TABLE
  • 范围分区 范围分区(Range Partition)根据为每个分区建立分区键的值范围将数据映射到分区。范围分区是生产系统中最常见的分区类型,通常在以时间维度(Date、Time Stamp)描述数据场景中使用。范围分区有两种语法格式,示例如下: VALUES LESS THAN的语法格式 对于从句是VALUE LESS THAN的语法格式,范围分区策略的分区键最多支持16列。 单列分区键示例如下: gaussdb=# CREATE TABLE range_sales_single_key ( product_id INT4 NOT NULL, customer_id INT4 NOT NULL, time DATE, channel_id CHAR(1), type_id INT4, quantity_sold NUMERIC(3), amount_sold NUMERIC(10,2) ) PARTITION BY RANGE (time) ( PARTITION date_202001 VALUES LESS THAN ('2020-02-01'), PARTITION date_202002 VALUES LESS THAN ('2020-03-01'), PARTITION date_202003 VALUES LESS THAN ('2020-04-01'), PARTITION date_202004 VALUES LESS THAN ('2020-05-01') ); gaussdb=# DROP TABLE range_sales_single_key; 其中date_202002表示2020年2月的分区,将包含分区键值从2020年2月1日到2020年2月29日的数据。 每个分区都有一个VALUES LESS子句,用于指定分区的非包含上限。大于或等于该分区键的任何值都将添加到下一个分区。除第一个分区外,所有分区都具有由前一个分区的VALUES LESS子句指定的隐式下限。可以为最高分区定义MAXVALUE关键字,MAXVALUE表示一个虚拟无限值,其排序高于分区键的任何其他可能值,包括空值。 多列分区键示例如下: gaussdb=# CREATE TABLE range_sales ( c1 INT4 NOT NULL, c2 INT4 NOT NULL, c3 CHAR(1) ) PARTITION BY RANGE (c1,c2) ( PARTITION p1 VALUES LESS THAN (10,10), PARTITION p2 VALUES LESS THAN (10,20), PARTITION p3 VALUES LESS THAN (20,10) ); INSERT INTO range_sales VALUES(9,5,'a'); INSERT INTO range_sales VALUES(9,20,'a'); INSERT INTO range_sales VALUES(9,21,'a'); INSERT INTO range_sales VALUES(10,5,'a'); INSERT INTO range_sales VALUES(10,15,'a'); INSERT INTO range_sales VALUES(10,20,'a'); INSERT INTO range_sales VALUES(10,21,'a'); INSERT INTO range_sales VALUES(11,5,'a'); INSERT INTO range_sales VALUES(11,20,'a'); INSERT INTO range_sales VALUES(11,21,'a'); gaussdb=# SELECT * FROM range_sales PARTITION (p1); c1 | c2 | c3 ----+----+---- 9 | 5 | a 9 | 20 | a 9 | 21 | a 10 | 5 | a (4 rows) gaussdb=# SELECT * FROM range_sales PARTITION (p2); c1 | c2 | c3 ----+----+---- 10 | 15 | a (1 row) gaussdb=# SELECT * FROM range_sales PARTITION (p3); c1 | c2 | c3 ----+----+---- 10 | 20 | a 10 | 21 | a 11 | 5 | a 11 | 20 | a 11 | 21 | a (5 rows) gaussdb=# DROP TABLE range_sales; 多列分区的分区规则如下: 从第一列开始比较。 如果插入的当前列小于分区当前列边界值,则直接插入。 如果插入的当前列等于分区当前列的边界值,则比较插入值的下一列与分区下一列边界值的大小。 如果插入的当前列大于分区当前列的边界值,则换下一个分区进行比较。 START END语法格式 对于从句是START END语法格式,范围分区策略的分区键最多支持1列。 示例如下: gaussdb=# -- 创建表空间 CREATE TABLESPACE startend_tbs1 LOCATION '/home/omm/startend_tbs1'; CREATE TABLESPACE startend_tbs2 LOCATION '/home/omm/startend_tbs2'; CREATE TABLESPACE startend_tbs3 LOCATION '/home/omm/startend_tbs3'; CREATE TABLESPACE startend_tbs4 LOCATION '/home/omm/startend_tbs4'; -- 创建临时schema CREATE SCHEMA tpcds; SET CURRENT_SCHEMA TO tpcds; -- 创建分区表,分区键是integer类型 CREATE TABLE tpcds.startend_pt (c1 INT, c2 INT) TABLESPACE startend_tbs1 PARTITION BY RANGE (c2) ( PARTITION p1 START(1) END(1000) EVERY(200) TABLESPACE startend_tbs2, PARTITION p2 END(2000), PARTITION p3 START(2000) END(2500) TABLESPACE startend_tbs3, PARTITION p4 START(2500), PARTITION p5 START(3000) END(5000) EVERY(1000) TABLESPACE startend_tbs4 ) ENABLE ROW MOVEMENT; -- 查看分区表信息 gaussdb=# SELECT relname, boundaries, spcname FROM pg_partition p JOIN pg_tablespace t ON p.reltablespace=t.oid and p.parentid='tpcds.startend_pt'::regclass ORDER BY 1; relname | boundaries | spcname -------------+------------+--------------- p1_0 | {1} | startend_tbs2 p1_1 | {201} | startend_tbs2 p1_2 | {401} | startend_tbs2 p1_3 | {601} | startend_tbs2 p1_4 | {801} | startend_tbs2 p1_5 | {1000} | startend_tbs2 p2 | {2000} | startend_tbs1 p3 | {2500} | startend_tbs3 p4 | {3000} | startend_tbs1 p5_1 | {4000} | startend_tbs4 p5_2 | {5000} | startend_tbs4 startend_pt | | startend_tbs1 (12 rows) --清理示例 gaussdb=# DROP TABLE tpcds.startend_pt; 父主题: 分区策略
  • 分区表统计信息 对于分区表,支持收集分区级统计信息,相关统计信息可以在pg_partition和pg_statistic系统表以及pg_stats和pg_ext_stats视图中查询。分区级统计信息适用于分区表进行静态剪枝后,分区表的扫描范围剪枝到单分区的场景下。分区级统计信息的支持范围为:分区级的page数和tuple数、单列统计信息、多列统计信息、表达式索引统计信息。 分区表统计信息有以下收集方式: 级联收集统计信息 指定具体单个分区收集统计信息 级联收集统计信息 分区级统计信息 父主题: 分区表查询优化
  • 场景描述 当对分区表使用Max/Min函数时,通常SQL引擎的实现方式是先通过Partition Iterator + PartitionScan对分区表做全量扫描然后进行Sort + Limit操作。如果分区是索引扫描,可以先对每个分区进行Limit操作,计算Max/Min值,最后在分区表上做Sort + Limit操作。这样分区表上做Sort时,由于每个分区已经获取Max/Min值,所以Sort的数据量跟分区数相同,这时极大的减少了Sort开销。
  • 对一级分区表移动分区 使用ALTER TABLE MOVE PARTITION可以对一级分区表移动分区。 例如,通过指定分区名将范围分区表range_sales的分区date_202001移动到表空间tb1中。 ALTER TABLE range_sales MOVE PARTITION date_202001 TABLESPACE tb1; 或者,通过指定分区值将列表分区表list_sales中'0'所对应的分区移动到表空间tb1中。 ALTER TABLE list_sales MOVE PARTITION FOR ('0') TABLESPACE tb1; 父主题: 移动分区
  • 加密模型 全密态数据库使用多级加密模型,加密模型中涉及3个对象:数据、列密钥和主密钥,以下是对3个对象的介绍: 数据: 指SQL语法中包含的数据,比如INSERT...VALUES ('data')语法中包含'data'。 指从数据库服务端返回的查询结果,比如执行SELECT...语法返回的查询结果。 密态数据库会在驱动中对SQL语法中属于加密列的数据进行加密,对数据库服务端返回的属于加密列的查询结果进行解密。 列密钥:数据由列密钥进行加密,列密钥由数据库驱动生成或由用户手动导入,列密钥密文存储在数据库服务端。 主密钥:列密钥由主密钥加密,主密钥由外部密钥管理者生成并存储。数据库驱动会自动访问外部密钥管理者,以实现对列密钥进行加解密。
  • 生成主密钥阶段 首次使用密态数据库时,需使用外部密钥管理服务生成至少一个主密钥,生成方式如下: 华为公有云场景 登录账号:进入华为云官网,注册并登录账号。 创建新用户:搜索并进入"身份认证服务",在"用户"中,通过"创建用户"按钮创建一个IAM用户,设置IAM密码,并为IAM用户设置使用"数据加密服务"的权限。 登录新用户:重新回到登录页面,选择"IAM用户"登录方式,使用新上一步创建的IAM用户进行登录。后续操作均由该IAM用户完成。 创建主密钥:选择"密钥管理"功能,并通过"创建密钥"按钮创建至少1个密钥,即主密钥。 记住主密钥ID:成功创建主密钥后,每个主密钥都有1个密钥ID。在后续使用密态数据过程中,需配置主密钥ID,数据库驱动会通过Restful接口访问该主密钥。 在生成主密钥后,需为数据驱动准备访问主密钥的参数,比如IAM用户名、项目ID等参数。华为云支持两种身份认证方式,两种方式需要的参数个数与参数类型不同,选择其中一种方式即可。下述步骤介绍如何获取这些参数: 方式一 aksk认证 AK、SK:首先登录华为云“控制台”,单击右上角用户名,进入“我的凭证”,选择“访问密钥”,通过“新增访问密钥”创建AK与SK,创建完成后下载密钥(即AK与SK)。 项目ID:在华为云控制台中,单击右上角用户名,并进入“我的凭证”,单击“API凭证”即可找到“项目ID”。 KMS服务器地址:https://kms.项目.myhuaweicloud.com/v1.0/项目ID/kms。 方式二 账号密码认证 IAM用户名、账号名、项目、项目ID:在华为云控制台中,单击右上角用户名,并进入“我的凭证”,可看到下图所示页面,该页面可获取4个参数:IAM用户名、账号名、项目、项目ID。 IAM服务器地址:https://iam.项目.myhuaweicloud.com/v3/auth/tokens。 IAM用户密码:IAM用户名对应的密码。 KMS服务器地址:https://kms.项目.myhuaweicloud.com/v1.0/项目ID/kms。
  • 整体流程 在使用全密态数据库的过程中,主要流程包括如下四个阶段,本节介绍整体流程,使用gsql操作密态数据库、使用JDBC操作密态数据库、使用Go驱动操作密态数据库章节介绍详细使用流程。 一、生成主密钥阶段:首先,用户需在外部密钥管理中生成主密钥。外部密钥管理分为多种,包括:华为云密钥服务,根据使用场景选择其中一种。生成主密钥后,需在外部密钥管理中,准备访问主密钥的参数,以供数据库使用。 二、执行DDL阶段:在本阶段,用户可使用密态数据库的密钥语法依次定义主密钥和列密钥,然后定义表并指定表中某列为加密列。定义主密钥和列密钥的过程中,需访问上一阶段生成的主密钥。 三、执行DML阶段:在创建加密表后,用户可直接执行包含但不限于INSERT、SELECT、UPDATE、DELETE等语法,数据库驱动会自动根据上一阶段的加密定义自动对加密列中的数据进行加解密。 四、清理阶段:依次删除加密表、列密钥和主密钥。
共100000条