华为云用户手册

  • 向二级分区表新增二级分区 使用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命令新增二级分区。 父主题: 新增分区
  • 事务回滚 回滚是在事务运行的过程中发生了故障等异常情形下,事务不能继续执行,系统需要将事务中已完成的修改操作进行撤销。Astore、Ubtree没有回滚段,自然没有这个专门的回滚动作。Ustore为了性能考虑,它的回滚流程结合了同步、异步和页面级回滚等3种形式。 同步回滚 有三种情况会触发事务的同步回滚: 事务块中的ROLLBACK关键字会触发同步回滚。 事务运行过程中如果发生ERROR级别报错,此时的COMMIT关键字与ROLLBACK功能相同,也会触发同步回滚。 事务运行过程中如果发生FATAL/PANIC级别报错,在线程退出前会尝试将该线程绑定的事务进行一次同步回滚。 异步回滚 同步回滚失败或者在系统宕机后再次重启时,会由Undo回收线程为未回滚完成的事务发起异步回滚任务,立即对外提供服务。由异步回滚任务发起线程undo launch负责拉起异步回滚工作线程undo worker,再由异步回滚工作线程实际执行回滚任务。undo launch线程最多可以同时拉起5个undo worker线程。 页面级回滚 当事务需要回滚但还未回滚到本页面时,如果其他事务需要复用该事务所占用的TD,就会在复用前对该事务在本页面的所有修改执行页面级回滚。页面级回滚只负责回滚事务在本页面的修改,不涉及其他页面。 Ustore子事务的回滚由ROLLBACK TO SAVEPOINT语句控制,子事务回滚后父事务可以继续运行,子事务的回滚不影响父事务的事务状态。如果一个事务在回滚时还存在未释放的子事务,该事务回滚前会先执行子事务的回滚,所有子事务回滚完毕后才会进行父事务的回滚。 父主题: Ustore事务模型
  • 数据分区查找优化 分区表对数据查找方面的帮助主要体现在对分区键进行谓词查询场景,例如一张以月份Month作为分区键的表,如图1所示。如果以普通表的方式设计表结构则需要访问表全量的数据(Full Table Scan),如果以日期为分区键重新设计该表,那么原有的全表扫描会被优化成为分区扫描。当表内的数据量很大同时具有很长的历史周期时,由于扫描数据缩减所带来的性能提升会有明显的效果,如图2所示。 图1 分区表示例图 图2 分区表剪枝示例图 父主题: 大容量数据库
  • 对一级分区表交换分区 使用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; 父主题: 交换分区
  • 删除分区 用户可以使用删除分区的命令来移除不需要的分区。删除分区可以通过指定分区名或者分区值来进行。 删除分区不能作用于HASH分区上。 执行删除分区命令会使得Global索引失效,可以通过UPDATE GLOBAL INDEX子句来同步更新Global索引,或者用户自行重建Global索引。 删除分区时,如果该分区上带有仅属于当前分区的分类索引时,则会级联删除分类索引。 对一级分区表删除分区 对二级分区表删除一级分区 对二级分区表删除二级分区 父主题: 分区表运维管理
  • 使用和管理分区表 分区表支持大部分非分区表的相关功能,具体可以参考《开发指南》中常规表的各类操作语法相关资料。 除此之外,分区表还支持大量的分区级操作命令,包括分区级DQL/DML(如SELECT、INSERT、UPDATE、DELETE、UPSERT、MERGE INTO)、分区级DDL(如ADD、DROP、TRUNCATE、EXCHANGE、SPLIT、MERGE、MOVE、RENAME)、分区VACUUM/ANALYZE、分类分区索引等。相关命令使用方法请参见分区表DQL/DML、分区索引、分区表运维管理、以及《开发指南》中各个语法命令对应的章节。 分区级操作命令一般通过指定分区名或者分区值的方式进行,比如语法命令可能是如下情形: sql_action [ t_name ] { PARTITION | SUBPARTITION } { p_name | (p_name) }; sql_action [ t_name ] { PARTITION | SUBPARTITION } FOR (p_value); 通过指定分区名p_name或指定分区值p_value来定向操作某个特定分区,此时业务只会作用于对象分区,而不会影响其他任何分区。如果通过指定分区名p_name来执行业务,数据库会匹配p_name对应的分区,该分区不存在则业务提示异常;如果通过指定分区值p_value来执行业务,数据库会匹配p_value值所属分区。 比如定义有如下的分区表: gaussdb=# CREATE TABLE list_01 ( id INT, role VARCHAR(100), data VARCHAR(100) ) PARTITION BY LIST (id) ( PARTITION p_list_1 VALUES(0,1,2,3,4), PARTITION p_list_2 VALUES(5,6,7,8,9), PARTITION p_list_3 VALUES(DEFAULT) ); gaussdb=# DROP TABLE list_01; 指定分区业务中,PARTITION p_list_1与PARTITION FOR (4)等价,为同一个分区;PARTITION p_list_3与PARTITION FOR (12)等价,为同一个分区。 父主题: 分区基本使用
  • 接口设计 新增控制参数 新增逻辑解码控制参数,用于控制DDL的反解析流程以及输出形式。可通过JDBC接口或者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_ LOG ICALDDLMSG_ID。其定义如下: 名称 类型 意义 db_id OID 数据库ID rel_id OID 表ID csn CommitSeqNo CS N快照 cid CommandId Command ID tag_type NodeTag DDL类型 message_size Size 日志内容长度 filter_message_size Size 日志中白名单过滤信息长度 message char * DDL内容
  • 功能描述 数据库在执行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 ] decode-style指定格式 输出的格式由decode-style参数控制,如当decode-style='j'时,输出格式如下: {"TDDL":"CREATE TABLE public.test_create_table_a (a pg_catalog.int4) WITH (orientation = 'row', compression = 'no') NOCOMPRESS"} 其中语句中也包含Schema名称。
  • 分区表统计信息 对于分区表,支持收集分区级统计信息,相关统计信息可以在pg_partition和pg_statistic系统表以及pg_stats和pg_ext_stats视图中查询。分区级统计信息适用于分区表进行静态剪枝后,分区表的扫描范围剪枝到单分区的场景下。分区级统计信息的支持范围为:分区级的page数和tuple数、单列统计信息、多列统计信息、表达式索引统计信息。 分区表统计信息有以下收集方式: 级联收集统计信息 指定具体单个分区收集统计信息 级联收集统计信息 分区级统计信息 父主题: 分区表查询优化
  • Local索引分区重建/不可用 使用ALTER INDEX PARTITION可以设置Local索引分区是否可用。 使用ALTER TABLE MODIFY PARTITION可以设置分区表上指定分区的所有索引分区是否可用。这个语法如果作用于二级分区表的一级分区,数据库会将这个一级分区下的所有二级分区均进行设置。 使用ALTER TABLE MODIFY SUBPARTITION可以设置二级分区表上指定二级分区的所有索引分区是否可用。 例如,假设分区表range_sales上存在两张Local索引range_sales_idx1和range_sales_idx2,假设其在分区date_202001上对应的索引分区名分别为range_sales_idx1_part1和range_sales_idx2_part1。 下面给出了维护分区表分区索引的语法: 可以通过如下命令设置分区date_202001上的所有索引分区均不可用。 ALTER TABLE range_sales MODIFY PARTITION date_202001 UNUSABLE LOCAL INDEXES; 或者通过如下命令单独设置分区date_202001上的索引分区range_sales_idx1_part1不可用。 ALTER INDEX range_sales_idx1 MODIFY PARTITION range_sales_idx1_part1 UNUSABLE; 可以通过如下命令重建分区date_202001上的所有索引分区。 ALTER TABLE range_sales MODIFY PARTITION date_202001 REBUILD UNUSABLE LOCAL INDEXES; 或者通过如下命令单独重建分区date_202001上的索引分区range_sales_idx1_part1。 ALTER INDEX range_sales_idx1 REBUILD PARTITION range_sales_idx1_part1; 假设二级分区表list_range_sales上存在两张Local索引list_range_sales_idx1和list_range_sales_idx2,表下有一级分区channel1,其下属二级分区有channel1_product1、channel1_product2、channel1_product3,二级分区channel1_product1上对应的索引分区名分别为channel1_product1_idx1和channel1_product1_idx2。 下面给出了维护二级分区表一级分区索引的语法: 可以通过如下命令设置分区channel1下属二级分区的所有索引分区均不可用,包括二级分区channel1_product1、channel1_product2、channel1_product3。 ALTER TABLE list_range_sales MODIFY PARTITION channel1 UNUSABLE LOCAL INDEXES; 可以通过如下命令重建分区channel1下属二级分区的所有索引分区。 ALTER TABLE list_range_sales MODIFY PARTITION channel1 REBUILD UNUSABLE LOCAL INDEXES; 下面给出了维护二级分区表二级分区索引的语法: 可以通过如下命令单独设置二级分区channel1_product1上的所有索引分区均不可用。 ALTER TABLE list_range_sales MODIFY SUBPARTITION channel1_product1 UNUSABLE LOCAL INDEXES; 可以通过如下命令重建二级分区channel1_product1上的所有索引分区。 ALTER TABLE list_range_sales MODIFY SUBPARTITION channel1_product1 REBUILD UNUSABLE LOCAL INDEXES; 或者通过如下命令单独设置二级分区channel1_product1上的索引分区channel1_product1_idx1不可用。 ALTER INDEX list_range_sales_idx1 MODIFY PARTITION channel1_product1_idx1 UNUSABLE; 通过如下命令单独重建二级分区channel1_product1上的索引分区channel1_product1_idx1。 ALTER INDEX list_range_sales_idx1 REBUILD PARTITION channel1_product1_idx1; 父主题: 分区表索引重建/不可用
  • DQL/DML-DDL同分区并发 GaussDB 不支持同分区的DQL/DML-DDL并发,后触发业务会被先触发业务阻塞。 原则上,不建议用户在进行分区DDL时,同时对该分区进行DQL/DML操作,因为目标分区存在一个状态的突变过程,可能会导致业务的查询结果不符合预期。 如果由于业务模型不合理、无法剪枝等场景导致的DQL/DML和DDL作用分区有重叠时,考虑两种场景: 场景一:先触发DQL/DML,再触发DDL。DDL会被阻塞,等DQL/DML提交后再进行。 场景二:先触发DDL,再触发DQL/DML。DQL/DML会被阻塞,等DDL提交后再进行,由于分区元信息发生了变更,可能导致预期不合理。为了保证数据一致性,预期结果按照如下规则制定。 在DQL/DML业务期间,如果对执行DQL/DML操作的分区,同时做多次分区DDL操作,有低概率出现报错,报错原因:分区找不到,分区已经被DDL删除。 ADD分区 ADD分区会产生一个新的分区,这个新分区对期间触发的DQL/DML操作均是不可见的,无阻塞期。 DROP分区 DROP分区会将已有分区进行删除,期间触发的目标分区DQL/DML操作会被阻塞,阻塞完成后跳过对该分区的处理。 TRUNCATE分区 TRUNCATE分区会将已有分区清空数据,期间触发的目标分区DQL/DML操作会被阻塞,阻塞完成后继续对该分区进行处理。 注意期间触发的目标分区查询是查不到数据的,因为TRUNCATE操作提交后目标分区中不存有任何数据。 EXCHANGE分区 EXCHANGE分区会将一个已有分区与普通表进行交换,期间触发的目标分区DQL/DML操作会被阻塞,阻塞完成后继续对该分区进行处理,该分区的实际数据对应原普通表。 例外:如果分区表上存在GLOBAL索引,EXCHANGE命令带来UPDATE GLOBAL INDEX子句,且期间触发的分区表查询使用了GLOBAL索引,由于无法查询到交换后分区上的数据,在阻塞完成后查询业务会报错。 ERROR: partition xxxxxx does not exist on relation "xxxxxx" DETAIL: this partition may have already been dropped by cocurrent DDL operations EXCHANGE PARTITION SPLIT分区 SPLIT分区会将一个分区分割为多个分区,即使其中一个新分区与旧分区名字相同,也视为不同的分区。期间触发的目标分区DQL/DML操作会被阻塞,阻塞完成后业务报错。 ERROR: partition xxxxxx does not exist on relation "xxxxxx" DETAIL: this partition may have already been dropped by cocurrent DDL operations SPLIT PARTITION MERGE分区 MERGE分区会将多个分区合并为一个分区,如果合并后的分区与其中一个旧分区A名字相同,逻辑上视为相同分区。期间触发的目标分区DQL/DML操作会被阻塞,阻塞完成后,根据目标分区类型判断,如果目标分区是旧分区A,则作用于新分区;如果目标分区为其他旧分区,则业务报错。 ERROR: partition xxxxxx does not exist on relation "xxxxxx" DETAIL: this partition may have already been dropped by cocurrent DDL operations MERGE PARTITION RENAME分区 RENAME分区不会变更分区结构信息,期间触发的DQL/DML操作不会出现任何异常,但会被阻塞,直到RENAME操作提交。 MOVE分区 MOVE分区不会变更分区结构信息,期间触发的DQL/DML操作不会出现任何异常,但会被阻塞,直到MOVE操作提交。
  • GaussDB内核R2版本 Ustore增加新的基于原位更新的行存储引擎Ustore,首次实现新、旧版本记录的分离存储。 Ustore增加回滚段模块。 Ustore增加回滚过程,支持同步/异步/页内模式。 Ustore增加支持事务的增强版本B-tree。 Astore增加闪回功能,支持闪回表/闪回查询/闪回Drop/闪回Truncate。 Ustore不支持的特性包括分布式并行查询/Table Sampling/Global Temp Table/在线创建/重建索引/极致RTO/Vacuum Full/列约束DEFERRABLE以及INITIALLY DEFERRED。 父主题: 存储引擎更新说明
  • 创建二级分区表 二级分区表,可以看成是对一级分区表的扩展,在二级分区表中第一层分区是一张逻辑表并不实际存储数据,数据实际是存储在二级分区节点上的。从实现上而言,二级分区表的分区方案是由两个一级分区的嵌套而来,一级分区的分区方案详见章节CREATE TABLE PARTITION。常见的二级分区表组合方案有:Range-Range分区、Range-List分区、Range-Hash分区、List-Range分区、List-List分区、List-Hash分区、Hash-Range分区、Hash-List分区、Hash-Hash分区等。目前二级分区仅支持行存表,二级分区创建的示例如下: CREATE TABLE [ IF NOT EXISTS ] subpartition_table_name ( [ /* 该部份继承于普通表的Create Table */ { column_name data_type [ COLLATE collation ] [ column_constraint [ ... ] ] | table_constraint | LIKE source_table [ like_option [...] ] } [, ... ] ] ) [ WITH ( {storage_parameter = value} [, ... ] ) ] [ COMPRESS | NOCOMPRESS ] [ TABLESPACE tablespace_name ] /* 二级分区定义的部分,只有list分区策略支持申明AUTOMATIC */ PARTITION BY {RANGE | LIST | HASH} (partKey) [ AUTOMATIC ] SUBPARTITOIN BY {RANGE | LIST | HASH} (partKey) [ AUTOMATIC ] ( PARTITION partition_name partExpr… /* 第一层分区 */ ( SUBPARTITION partition_name partExpr … /* 第二层分区 */ SUBPARTITION partition_name partExpr … /* 第二层分区 */ ), PARTITION partition_name partExpr… /* 第一层分区 */ ( SUBPARTITION partition_name partExpr … /* 第二层分区 */ SUBPARTITION partition_name partExpr … /* 第二层分区 */ ), … ) [ { ENABLE | DISABLE } ROW MOVEMENT ]; 规格约束: 二级分区表支持LIST/HASH/RANGE分区的任意两两组合。 二级分区表支持任一层LIST申明自动扩展。 二级分区表的第二层分区采用LIST自动扩展时,建表语句中第二层分区定义不能为空。 二级分区表场景中仅支持单分区键。 二级分区表中不支持INTERVAL类型分区的组合。 二级分区表场景中,分区总数上限为1048575。
  • 创建普通分区表(创建一级分区表) 由于SQL语言功能强大和灵活多样性,SQL语法树通常比复杂,分区表同样如此,分区表的创建可以理解成在原有非分区表的基础上新增表分区属性,因此分区表的语法接口可以看成是对原有非分区表CREATE TABLE语句进行扩展PARTITION BY语句部分,同时指定分区相关的三个核元素: 分区类型(partType):描述分区表的分区策略,分别有RANGE/INTERVAL/LIST/HASH。 分区键(partKey):描述分区表的分区列,目前RANGE/LIST分区支持多列(不超过16列)分区键,INTERVAL/HASH分区只支持单列分区。 分区表达式(partExpr):描述分区表的具体分区表方式,即键值与分区的对应映射关系。 这三部分重要元素在建表语句的Partition By Clause子句中体现,PARTITION BY partType (partKey) ( partExpr[,partExpr]…)。示例如下: CREATE TABLE [ IF NOT EXISTS ] partition_table_name ( [ /* 该部分继承于普通表的Create Table */ { column_name data_type [ COLLATE collation ] [ column_constraint [ ... ] ] | table_constraint | LIKE source_table [ like_option [...] ] }[, ... ] ] ) [ WITH ( {storage_parameter = value} [, ... ] ) ] [ COMPRESS | NOCOMPRESS ] [ TABLESPACE tablespace_name ] /* 范围分区场景,若申明INTERVAL子句则为间隔分区场景 */ PARTITION BY RANGE (partKey) [ INTERVAL ('interval_expr') [ STORE IN (tablespace_name [, ... ] ) ] ] ( partition_start_end_item [, ... ] partition_less_then_item [, ... ] ) /* 列表分区场景,若申明AUTOMATIC则支持list自动扩展 */ PARTITION BY LIST (partKey) [ AUTOMATIC ] ( PARTITION partition_name VALUES (list_values_clause) [ TABLESPACE tablespace_name [, ... ] ] ... ) /* 哈希分区场景 */ PARTITION BY HASH (partKey) ( PARTITION partition_name [ TABLESPACE tablespace_name [, ... ] ] ... ) /* 开启/关闭分区表行迁移 */ [ { ENABLE | DISABLE } ROW MOVEMENT ]; 规格约束: RANGE/LIST分区最大支持16个分区键,INTERVAL/HASH分区均只支持1个分区键,二级分区只支持1个分区键。 INTERVAL分区仅支持数值类型和日期/时间类型,INTERVAL分区不支持在二级分区表中创建。 INTERVAL分区表定义不能有MAXVALUE分区,LIST自动扩展分区表不能定义有DEFAULT分区。 除哈希分区外,分区键不能插入空值,否则DML语句会进行报错处理。唯一例外:RANGE分区表定义有MAXVALUE分区/LIST分区表定义有DEFAULT分区。 分区数最大值为1048575个,可以满足大部分业务场景的诉求。但分区数增加会导致系统中文件数增加,影响系统的性能,一般对于单个表而言不建议分区数超过200。
  • 表分区技术 表分区技术(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索引个数相同,且对应索引的信息严格一致。 普通表和分区的表约束个数相同,且对应表约束的信息严格一致。 普通表不可以是临时表。 普通表和分区表上不可以有动态数据脱敏,行访问控制约束。 对一级分区表交换分区 对二级分区表交换二级分区 父主题: 分区表运维管理
  • 生成主密钥阶段 首次使用密态数据库时,需使用外部密钥管理服务生成至少一个主密钥,生成方式如下: 华为公有云场景 登录账号:进入华为云官网,注册并登录账号。 创建新用户:搜索并进入"身份认证服务",在"用户"中,通过"创建用户"按钮创建一个 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等语法,数据库驱动会自动根据上一阶段的加密定义自动对加密列中的数据进行加解密。 四、清理阶段:依次删除加密表、列密钥和主密钥。
  • 加密模型 全密态数据库使用多级加密模型,加密模型中涉及3个对象:数据、列密钥和主密钥,以下是对3个对象的介绍: 数据: 指SQL语法中包含的数据,比如INSERT...VALUES ('data')语法中包含'data'。 指从数据库服务端返回的查询结果,比如执行SELECT...语法返回的查询结果。 密态数据库会在驱动中对SQL语法中属于加密列的数据进行加密,对数据库服务端返回的属于加密列的查询结果进行解密。 列密钥:数据由列密钥进行加密,列密钥由数据库驱动生成或由用户手动导入,列密钥密文存储在数据库服务端。 主密钥:列密钥由主密钥加密,主密钥由外部密钥管理者生成并存储。数据库驱动会自动访问外部密钥管理者,以实现对列密钥进行加解密。
  • 对一级分区表合并分区 使用ALTER TABLE MERGE PARTITIONS可以将多个分区合并为一个分区。 例如,将范围分区表range_sales的分区date_202001和date_202002合并为一个新的分区,并更新Global索引。 ALTER TABLE range_sales MERGE PARTITIONS date_202001, date_202002 INTO PARTITION date_2020_old UPDATE GLOBAL INDEX; 对间隔分区表的间隔分区完成合并分区操作之后,源分区之前的间隔分区会变成范围分区。 父主题: 合并分区
  • 示例 创建表 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;
  • 约束 分区表索引分为LOCAL索引与GLOBAL索引:LOCAL索引与某个具体分区绑定,而GLOBAL索引则对应整个分区表。 唯一约束和主键约束的约束键包含所有分区键则创建LOCAL索引,否则创建GLOBAL索引。 在创建LOCAL索引时,可以通过FOR { partition_name | ( partition_value [, ...] ) }子句,指定在单个分区上创建LOCAL索引,此类索引在其他分区上不生效,后续新增的分区也不会自动创建该索引。需要注意的是,当前仅静态剪枝到单个分区的计划支持生成分类索引的查询路径。
  • 不支持场景 物化视图中不支持多表Join连接计划以及subquery计划。 不支持WITH子句、GROUP BY子句、ORDER BY子句、LIMIT子句、WINDOW子句、DISTINCT算子、AGG算子,不支持除UNION ALL外的子查询。 除少部分ALTER操作外,不支持对物化视图中基表执行绝大多数DDL操作。 物化视图不支持增删改操作,只支持查询语句。 不支持用临时表/hashbucket/unlog/分区表创建物化视图。 不支持物化视图嵌套创建(即物化视图上创建物化视图)。 不支持UNLOGGED类型的物化视图,不支持WITH语法。 Ustore引擎不支持增量物化视图的创建和使用。
  • 对一级分区表删除分区 使用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命令删除分区。 父主题: 删除分区
  • RCR Uheap多版本管理 Ustore对其使用的heap做了如下重要的增强,简称Uheap。 Ustore RCR(Row Consistency Read)的多版本管理是基于数据行的行级多版本管理,不过Ustore将XID记录在了页面的TD(Transaction Directory)区域,区别于常见的将XID存储在数据行上,节省了页面空间。事务修改记录时,会将历史数据记录到Undo Row中,在Tuple中的td_id指向的TD槽上记录产生的Undo Row地址(zone_id, block no, page offset),并将新的数据覆盖写入页面。访问元组时,沿着版本链还原该元组,直到找到自己对应的版本。 父主题: RCR Uheap
  • 对二级分区表删除二级分区 使用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命令删除二级分区。 父主题: 删除分区
  • 对二级分区表交换二级分区 使用ALTER TABLE EXCHANGE SUBPARTITION可以对二级分区表交换二级分区。 例如,通过指定分区名将二级分区表range_list_sales的二级分区date_202001_channel1和普通表exchange_sales进行交换,不进行分区键校验,并更新Global索引。 ALTER TABLE range_list_sales EXCHANGE SUBPARTITION (date_202001_channel1) WITH TABLE exchange_sales WITHOUT VALIDATION UPDATE GLOBAL INDEX; 或者,通过指定分区值将二级分区表range_list_sales中('2020-01-08', '0')所对应的二级分区和普通表exchange_sales进行交换,进行分区校验并将不满足目标分区约束的数据插入到分区表的其他分区中。由于不带UPDATE GLOBAL INDEX子句,执行该命令后Global索引会失效。 ALTER TABLE range_list_sales EXCHANGE SUBPARTITION FOR ('2020-01-08', '0') WITH TABLE exchange_sales WITH VALIDATION VERBOSE; 不支持对二级分区表的一级分区交换分区。 父主题: 交换分区
  • 语法格式 创建增量物化视图 CREATE INCREMENTAL MATERIALIZED VIEW view_name AS query; 全量刷新物化视图 REFRESH MATERIALIZED VIEW view_name; 增量刷新物化视图 REFRESH INCREMENTAL MATERIALIZED VIEW view_name; 删除物化视图 DROP MATERIALIZED VIEW view_name; 查询物化视图 SELECT * FROM view_name;
  • 示例 -- 修改表的默认类型 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 INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM t1; CREATE MATERIALIZED VIEW --插入数据。 gaussdb=# INSERT INTO t1 VALUES(3, 3); INSERT 0 1 --增量刷新物化视图。 gaussdb=# REFRESH INCREMENTAL MATERIALIZED VIEW mv; REFRESH MATERIALIZED VIEW --查询物化视图结果。 gaussdb=# SELECT * FROM mv; c1 | c2 ----+---- 1 | 1 2 | 2 3 | 3 (3 rows) --插入数据。 gaussdb=# INSERT INTO t1 VALUES(4, 4); INSERT 0 1 --全量刷新物化视图。 gaussdb=# REFRESH MATERIALIZED VIEW mv; REFRESH MATERIALIZED VIEW --查询物化视图结果。 gaussdb=# select * from mv; c1 | c2 ----+---- 1 | 1 2 | 2 3 | 3 4 | 4 (4 rows) --删除物化视图,删除表。 gaussdb=# DROP MATERIALIZED VIEW mv; DROP MATERIALIZED VIEW gaussdb=# DROP TABLE t1; DROP TABLE
共100000条