-
示例 在表test_table中添加sales bigint列: 1 ALTER TABLE test_table ADD COLUMNS ( sales bigint COMMENT 'factory sales volume' );
将表test_table中sales列更名为my_sales: 1 ALTER TABLE test_table COLUMN sales RENAME TO my_sales;
-
语法格式 1
2
3
4
5
6
7
8
9 ALTER TABLE table_name DROP PARTITIONS ( col_name = col_value [, ... ] ) [, ... ];
ALTER TABLE table_name ADD COLUMNS ( col_name col_type [ COMMENT col_comment ] [, ... ] );
ALTER TABLE table_name DROP COLUMNS ( col_name [, ... ] );
ALTER TABLE table_name COLUMN col_name RENAME TO col_name_new;
ALTER TABLE table_name ALTER COLUMN col_name col_name_new col_type [ COMMENT col_comment ];
ALTER TABLE table_name RENAME TO table_name_new;
ALTER TABLE table_name SET TABLEPROPERTIES ( option_key = option_value [, ... ] );
ALTER TABLE table_name UNSET TABLEPROPERTIES ( option_key [, ... ] );
ALTER TABLE table_name UPDATE COLUMNS;
-
语法格式 1
2
3
4
5
6
7
8
9 CREATE EXTERNAL TABLE [ IF NOT EXISTS ] [schema_name.]table_name
[ ( col_name col_type [ COMMENT col_comment ] [, ... ] ) ]
[ COMMENT table_comment ]
[ PARTITION BY ( col_name col_type COMMENT col_comment [, ... ] ) ]
[ CLUSTERED BY (col_name [,...]) INTO ( bucket_num ) BUCKETS ]
[ TABLEPROPERTIES ( option_key = option_value [, ... ] ) ]
[ STORE AS table_format ]
[ LOCATION table_path ]
AS select_stmt;
-
参数说明 IF NOT EXISTS 如果存在同名表,则发出一个notice而不是抛出一个错误。 schema_name 表所属的数据库名,如果未指定数据库名时,则将在current_schema下建表。 table_name 创建表的表名,表名长度不可超过63个字符。 col_name 创建表的列名,列名长度不可超过63个字符。普通列和分区列的数量总和不可超过5000个。 col_type 创建表的列类型,列类型支持范围如下: 列类型 是否可以声明为分区列 是否支持ORC格式 是否支持PARQUET格式 是否支持Iceberg格式 SmallInt √ √ √ √ Int √ √ √ √ BigInt √ √ √ √ Float × √ √ √ Double × √ √ √ Decimal √ √ √ √ Numeric √ √ √ √ Timestamp √ √ √ √ Date √ √ √ √ Varchar √ √ √ √ Char √ √ √ √ Bool × √ √ √ Bytea × √ √ √ Text √ √ √ √ col_comment 列注释信息,可指定为任意字符串。 table_comment 表注释信息,可指定为任意字符串。 bucket_num bucket个数。 option_key = option_value 表级别参数设置,支持参数范围如下: 表1 option_key参数支持范围 option_key option_value 说明 适用范围 orc.compress zlib, snappy, lz4 ORC文件压缩方式。 ORC parquet.compression zlib, snappy, lz4 PARQUET文件压缩方式。 PARQUET julian_adjust true, false 是否转换为Julian日期。 PARQUET checkencoding high, low, no 是否检查字符编码。 ORC, PARQUET column_index_access true, false 读取时表定义列和文件列匹配方式,默认true为列索引匹配,false为列名匹配。 ORC, PARQUET filesize 1~1024的证书 生成外表文件大小。 ORC, PARQUET write.delete.mode copy-on-write, merge-on-read 设置delete时的模式:cow或mor。 Iceberg write.update.mode copy-on-write, merge-on-read 设置update时的模式:cow或mor。 write.merge.mode copy-on-write, merge-on-read 设置merge时的模式:cow或mor。 write.parquet.compression-codec zstd, zlib, lz4, snappy, gzip parquet文件的压缩方式。 write.merge.isolation-level snapshot, serializable merge命令的隔离级别。 write.metadata.delete-after-commit.enabled true, false 控制提交后是否删除最旧的跟踪版本元数据文件。 write.update.isolation-level snapshot, serializable update命令的隔离级别。 write.delete.isolation-level snapshot, serializable delete命令的隔离级别。 write.metadata.previous-versions-max 大于0的整数 要保留的旧元数据文件的数 table_format 表存储格式,支持ORC、PARQUET、ICEBERG三种存储格式。 table_path 表存储路径,必须为合法OBS路径,支持OBS对象桶和并行文件系统。如果该路径为OBS对象桶路径,则该表只读,否则该表支持读写。 select_stmt 查询语句。
-
描述 返回表的近似统计信息。 返回每一列的统计信息。 列 描述 column_name 列名(汇总行为NULL) data_size 列中所有值的总大小(以字节为单位) distinct_values_count 列中不同值的数量 nulls_fraction 列中值为NULL的部分 row_count 行数(仅针对摘要行返回) low_value 在此列中找到的最小值(仅对于某些类型) high_value 在此列中找到的最大值(仅适用于某些类型)
-
示例 SHOW STATS FOR orders;
SHOW STATS FOR (SELECT * FROM orders); 在 Analyze nation表之前: SHOW STATS FOR nation;
column_name | data_size | distinct_values_count | nulls_fraction | row_count | low_value | high_value
-------------|-----------|-----------------------|----------------|-----------|-----------|------------
name | NULL | NULL | NULL | NULL | NULL | NULL
regionkey | NULL | NULL | NULL | NULL | NULL | NULL
NULL | NULL | NULL | NULL | 6.0 | NULL | NULL
(3 rows) 在 Analyze nation表之后: Analyze nation;
ANALYZE: 6 rows
--查询分析后的结果
SHOW STATS FOR nation;
column_name | data_size | distinct_values_count | nulls_fraction | row_count | low_value | high_value
-------------|-----------|-----------------------|----------------|-----------|-----------|------------
name | 45.0 | 5.0 | 0.0 | NULL | NULL | NULL
regionkey | NULL | 2.0 | 0.0 | NULL | 0 | 2
NULL | NULL | NULL | NULL | 6.0 | NULL | NULL
(3 rows)
-
TEMPORARY | TEMP参数使用说明 LOCAL/VOLATILE临时表通过每个会话独立的以pg_temp开头的schema来保证只对当前会话可见,因此,不建议用户在日常操作中手动删除以pg_temp,pg_toast_temp开头的schema。 如果建表时不指定TEMPORARY/TEMP关键字,而指定表的schema为当前会话的pg_temp_开头的schema,则此表会被创建为临时表。 LOCAL临时表的所有相关元数据同普通表类似,都存储在系统表内,而VOLATILE临时表会将除schema外的相关表结构元数据直接存储在内存中。所以相对本地临时表而言,VOLATILE临时表有更多约束: 当前CN或DN重启之后,对应实例上的内存数据丢失,相关volatile临时表会失效。 VOLATILE临时表当前不支持ALTER/GRANT等修改表结构相关操作。 VOLATILE临时表和LOCAL临时表共用一种临时schema,所以在同一session中,VOLATILE临时表和LOCAL临时表不能存在同名表。 VOLATILE临时表信息不存储在系统表内,所以无法通过对系统表执行DML语句查询到VOLATILE相关元数据。 VOLATILE临时表仅支持普通的行存、列存表,不支持delta表、时序表、冷热表。 不支持基于VOLATILE临时表创建视图。 不支持创建临时表时指定tablespace(VOLATILE临时表默认tablespace均为pg_volatile)。 创建VOLATILE临时表时不支持指定约束:CHECK约束、UNIQUE约束、主键约束、触发器约束、EXCLUDE约束、PARTIAL CLUSTER约束。 GLOBAL临时表的所有相关元数据同普通表类似,都存储在系统表内。 GLOBAL临时表与LOCAL临时表不同的是,会话退出时元数据不会删除,但会话的数据会删除。不同会话的数据独立,但共享同一份GLOBAL临时表的元数据。 全局临时表的schema与普通表类似,不是以pg_temp开头的schema,但与LOCAL/VOLATILE临时表不同,所以可以与LOCAL/VOLATILE临时表同名。 全局临时表仅支持普通的行存、列存表,不支持delta表、时序表、冷热表。 不支持操作其他逻辑集群的全局临时表。
-
DISTRIBUTE BY参数使用说明 指定表如何在节点之间分布或者复制。 取值范围: REPLICATION:表的每一行存在所有数据节点(DN)中,即每个数据节点都有完整的表数据。 ROUNDROBIN:表的每一行被轮番地发送给各个DN,因此数据会被均匀地分布在各个DN中。(ROUNDROBIN仅8.1.2及以上版本支持) HASH (column_name ) :对指定的列进行Hash,通过映射,把数据分布到指定DN。 当指定DISTRIBUTE BY HASH (column_name)参数时,创建主键和唯一索引必须包含“ column_name”列。 当被参照表指定DISTRIBUTE BY HASH (column_name)参数时,参照表的外键必须包含“ column_name”列。 如果TO GROUP指定为复制表节点组(8.1.2及以上版本支持),DISTRIBUTE BY必须指定为REPLICATION。如果没有指定DISTRIBUTE BY,创建的表会自动设置为复制表。 单节点集群(单机部署)由于只有单DN,因此分布规则会被忽略,也不支持针对分布规则的修改。 默认值:由GUC参数default_distribution_mode控制。 当default_distribution_mode=roundrobin时,DISTRIBUTE BY的默认值按如下规则选取: 若建表时包含主键/唯一约束,则选取HASH分布,分布列为主键/唯一约束对应的列。 若建表时不包含主键/唯一约束,则选取ROUNDROBIN分布。 当default_distribution_mode=hash时,DISTRIBUTE BY的默认值按如下规则选取: 若建表时包含主键/唯一约束,则选取HASH分布,分布列为主键/唯一约束对应的列。 若建表时不包含主键/唯一约束,但存在数据类型支持作分布列的列,则选取HASH分布,分布列为第一个数据类型支持作分布列的列。 若建表时不包含主键/唯一约束,也不存在数据类型支持作分布列的列,选取ROUNDROBIN分布。 以下数据类型支持作为分布列: INTEGER TYPES:TINYINT,SMALLINT,INT,BIGINT,NUMERIC/DECIMAL CHARACTER TYPES:CHAR,BPCHAR,VARCHAR,VARCHAR2,NVARCHAR2,TEXT DATE/TIME TYPES:DATE,TIME,TIMETZ,TIMESTAMP,TIMESTAMPTZ,INTERVAL,SMALLDATETIME 在建表时,选择分布列和分区键可对SQL查询性能产生重大影响。因此,需要根据一定策略选择合适的分布列和分区键。 选择合适的分布列 对于采用散列(Hash)方式的数据分布表,一个合适的分布列应将一个表内的数据,均匀分散存储在多个DN内,避免出现数据倾斜现象(即多个DN内数据分布不均)。请按照如下原则判定合适的分布列: 判断是否已发生数据倾斜现象。 连接数据库,执行如下语句,查看各DN内元组数目。命令中的斜体部分tablename,请填入待分析的表名。 SELECT a.count,b.node_name FROM (SELECT count(*) AS count,xc_node_id FROM tablename GROUP BY xc_node_id) a, pgxc_node b WHERE a.xc_node_id=b.node_id ORDER BY a.count DESC; 如果各DN内元组数目相差较大(如相差数倍、数十倍),则表明已发生数据倾斜现象,请按照下面原则调整分布列。 重新选择分布列,可通过ALTER TABLE语句调整分布列,选择原则如下: 分布列的列值应比较离散,以便数据能够均匀分布到各个DN。例如,考虑选择表的主键为分布列,如在人员信息表中选择身份证号码为分布列。 在满足上面原则的情况下,考虑选择查询中的连接条件为分布列,以便Join任务能够下推到DN中执行,且减少DN之间的通信数据量。 如果找不到一个合适的分布列,使数据能够均匀分布到各个DN,那么可以考虑使用REPLICATION或ROUNDROBIN的数据分布方式。由于REPLICATION的数据分布方式会在每个DN中存放完整的数据,因此在表较大且找不到合适的分布列时,推荐使用ROUNDROBIN的数据分布方式。(ROUNDROBIN分布方式8.1.2及以上版本支持) 选择合适的分区键 数据分区功能,可根据表的一列或者多列,将要插入表的记录分为若干个范围(这些范围在不同的分区里没有重叠)。然后为每个范围创建一个分区,用来存储相应的数据。 调整分区键,使每次查询结果尽可能存储在相同或者最少的分区内(称为“分区剪枝”),通过获取连续I/O大幅度提升查询性能。 实际业务中,经常将时间作为查询对象的过滤条件,因此,可考虑选择时间列为分区键,键值范围可根据总数据量、一次查询数据量调整。
-
LIKE参数使用说明 新表与源表之间在创建动作完毕之后是完全无关的。在源表做的任何修改都不会传播到新表中,并且也不可能在扫描源表的时候包含新表的数据。 被复制的列和约束并不使用相同的名字进行融合。如果明确的指定了相同的名字或者在另外一个LIKE子句中,将会报错。 源表上的字段缺省表达式或者ON UPDATE表达式只有在指定INCLUDING DEFAULTS时,才会复制到新表中。缺省是不包含缺省表达式的,即新表中的所有字段的缺省值都是NULL。 源表上的CHECK约束仅在指定INCLUDING CONSTRAINTS时,会复制到新表中,而其他类型的约束永远不会复制到新表中。非空约束总是复制到新表中。此规则同时适用于表约束和列约束。 如果指定了INCLUDING INDEXES,则源表上的索引也将在新表上创建,默认不建立索引。 如果指定了INCLUDING STORAGE,则复制列的STORAGE设置会复制到新表中,默认情况下不包含STORAGE设置。 如果指定了INCLUDING COMMENTS,则源表列、约束和索引的注释会复制到新表中。默认情况下,不复制源表的注释。 如果指定了INCLUDING PARTITION,则源表的分区定义会复制到新表中,同时新表将不能再使用PARTITION BY子句。默认情况下,不拷贝源表的分区定义。 如果指定了INCLUDING RELOPTIONS,则源表的存储参数(即源表的WITH子句)会复制到新表中。默认情况下,不复制源表的存储参数。 WITH中的'PERIOD','TTL'为partition相关参数,LIKE INCLUDING RELOPTIONS不会复制到新表中,若要复制需INCLUDING PARTITION。 如果指定了INCLUDING DISTRIBUTION,则源表的分布信息会复制到新表中,包括分布类型和分布列,同时新表将不能再使用DISTRIBUTE BY子句。默认情况下,不拷贝源表的分布信息。 如果指定了INCLUDING DROPCOLUMNS,则源表被删除的列信息会被复制到新表中。默认情况下,不复制源表的删除列信息。 INCLUDING ALL包含了INCLUDING DEFAULTS、INCLUDING CONSTRAINTS、INCLUDING INDEXES、INCLUDING STORAGE、INCLUDING COMMENTS、INCLUDING PARTITION、INCLUDING RELOPTIONS、INCLUDING DISTRIBUTION和INCLUDING DROPCOLUMNS的内容。 如果指定了EXCLUDING,则表示不包括指定的参数。 如果是OBS冷热表,INCLUDING PARTITION后新表所有分区均为本地热分区。 如果源表包含serial、bigserial、smallserial类型,或者源表字段的默认值是sequence,且sequence属于源表(通过CREATE SEQUENCE ... OWNED BY创建),这些Sequence不会关联到新表中,新表中会重新创建属于自己的sequence。这和之前版本的处理逻辑不同。如果用户希望源表和新表共享Sequence,需要首先创建一个共享的Sequence(避免使用OWNED BY),并配置为源表字段默认值,这样创建的新表会和源表共享该Sequence。 不建议将其他表私有的Sequence配置为源表字段的默认值,尤其是其他表只分布在特定的NodeGroup上,这可能导致CREATE TABLE ... LIKE执行失败。另外,如果源表配置其他表私有的Sequence,当该表删除时Sequence也会连带删除,这样源表的Sequence将不可用。如果用户希望多个表共享Sequence,建议创建共享的Sequence。
-
语法格式 1
2
3
4
5
6
7
8
9
10
11
12 CREATE [ [ GLOBAL | LOCAL | VOLATILE ] { TEMPORARY | TEMP } | UN
LOG GED ] TABLE [ IF NOT EXISTS ] table_name
{ ({ column_name data_type [ compress_mode ] [ COLLATE collation ] [ column_constraint [ ... ] ]
| table_constraint
| LIKE source_table [ like_option [...] ] }
[, ... ])|
LIKE source_table [ like_option [...] ] }
[ WITH ( {storage_parameter = value} [, ... ] ) ]
[ ON COMMIT { PRESERVE ROWS | DELETE ROWS } ]
[ COMPRESS | NOCOMPRESS ]
[ DISTRIBUTE BY { REPLICATION | ROUNDROBIN | { HASH ( column_name [,...] ) } } ]
[ TO { GROUP groupname | NODE ( nodename [, ... ] ) } ]
[ COMMENT [=] 'text' ];
其中列约束column_constraint为: 1
2
3
4
5
6
7
8
9
10
11 [ CONSTRAINT constraint_name ]
{ NOT NULL |
NULL |
CHECK ( expression ) |
DEFAULT default_expr |
ON UPDATE on_update_expr |
COMMENT 'text' |
UNIQUE [ NULLS [NOT] DISTINCT | NULLS IGNORE ] index_parameters |
PRIMARY KEY index_parameters |
REFEREN
CES reftable [ ( refcolumn ) ] }
[ DEFERRABLE | NOT DEFERRABLE | INITIALLY DEFERRED | INITIALLY IMMEDIATE ]
其中列的压缩可选项compress_mode为: 1 { DELTA | PREFIX | DICTIONARY | NUMSTR | NOCOMPRESS }
其中表约束table_constraint为: 1
2
3
4
5
6 [ CONSTRAINT constraint_name ]
{ CHECK ( expression ) |
UNIQUE [ NULLS [NOT] DISTINCT | NULLS IGNORE ] ( column_name [, ... ] ) index_parameters |
PRIMARY KEY ( column_name [, ... ] ) index_parameters |
PARTIAL CLUSTER KEY ( column_name [, ... ] ) }
[ DEFERRABLE | NOT DEFERRABLE | INITIALLY DEFERRED | INITIALLY IMMEDIATE ]
其中like选项like_option为: 1 { INCLUDING | EXCLUDING } { DEFAULTS | CONSTRAINTS | INDEXES | STORAGE | COMMENTS | PARTITION | RELOPTIONS | DISTRIBUTION | DROPCOLUMNS | ALL }
其中索引参数index_parameters为: 1 [ WITH ( {storage_parameter = value} [, ... ] ) ]
-
注意事项 列存表支持的数据类型请参考列存表支持的数据类型。 创建列存和HDFS分区表的数量建议不超过1000个。 表中的主键约束和唯一约束必须包含分布列。 不支持修改已有表的分布列数据类型。 行存REPLICATION分布表不支持将系统列设置为主键。 如果在建表过程中数据库系统发生故障,系统恢复后可能无法自动清除之前已创建的、大小为0的磁盘文件。此种情况出现概率小,不影响数据库系统的正常运行。 列存表支持PARTIAL CLUSTER KEY、主键和唯一表级约束,不支持外键表级约束。 列存表的字段约束只支持NULL、NOT NULL和DEFAULT常量值。 列存表支持delta表,受表级参数enable_delta控制是否开启,受参数deltarow_threshold控制进入delta表的阈值。不推荐使用列存带Delta表,否则会出现由于来不及merge而导致的磁盘膨胀以及性能劣化等问题。 冷热表仅支持列存分区表,依赖于可用的OBS服务。 冷热表仅支持默认表空间为default_obs_tbs,如需新增obs表空间可联系技术支持。 如需创建列存表,需显式设置orientation属性为column,存算分离版本如需创建本地表(数据全部存储在EVS盘),需显式指定colversion=2.0。 创建表后,不支持通过ALTER TABLE语法将非V3表切换为V3表(即colversion为2.0不支持切为3.0)。 V3表(即colversion=3.0,存算分离表,以下简称V3表)不支持设置delta表和列存二级分区。 V3表不支持设置为Hstore表、冷热表、时序表。 V3表不支持创建全局临时表和临时表,创建的临时表会自动转化为colversion=2.0的临时表。 不建议创建普通表时指定自定义TABLESPACE。 创建行存表时应避免指定COMPRESS压缩属性。 创建HASH分布的表对象时,要确保数据分布均匀(10G以上数据量的表,倾斜率控制在10%以内)。 创建REPLICATION分布的表对象,要确保表数据量控制在100万行以内。 创建HSTORE表时,必须确保数据库GUC参数设置满足以下条件: autovacuum设置为on。 autovacuum_max_workers_hstore取值大于0。 autovacuum_max_workers取值大于autovacuum_max_workers_hstore的取值。 针对存在时间字段的大表(数据量5000万行以上),必须设计成分区表,根据查询特征合理设计分区间隔。 针对有大批量数据增删改的表,索引个数建议控制在3个以内,最多不超过5个。 更多开发设计规范参见总体开发设计规范。
-
示例 创建范围分区表customer_address。 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 DROP TABLE IF EXISTS customer_address;
CREATE TABLE 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)
)
DISTRIBUTE BY HASH (ca_address_sk)
PARTITION BY RANGE(ca_address_sk)
(
PARTITION P1 VALUES LESS THAN(100),
PARTITION P2 VALUES LESS THAN(200),
PARTITION P3 VALUES LESS THAN(300)
);
创建示例list分区表。 DROP TABLE IF EXISTS data_list;
CREATE TABLE data_list(
id int,
time int,
sarlay decimal(12,2)
)PARTITION BY LIST (time)(
PARTITION P1 VALUES (202209),
PARTITION P2 VALUES (202210,202208),
PARTITION P3 VALUES (202211),
PARTITION P4 VALUES (202212),
PARTITION P5 VALUES (202301)
); modify_clause子句用于设置分区索引是否可用。 给分区表customer_address创建LOCAL索引student_grade_index,并指定分区的索引名称。 1
2
3
4
5
6 CREATE INDEX customer_address_index ON customer_address(ca_address_id) LOCAL
(
PARTITION P1_index,
PARTITION P2_index,
PARTITION P3_index
);
重建分区表customer_address中分区P1上的所有索引。 1 ALTER TABLE customer_address MODIFY PARTITION P1 REBUILD UNUSABLE LOCAL INDEXES;
设置分区表customer_address的分区P3上的所有索引不可用。 1 ALTER TABLE customer_address MODIFY PARTITION P3 UNUSABLE LOCAL INDEXES;
add_clause子句用于为指定的分区表添加一个或多个分区。 为范围分区表customer_address增加分区。 1 ALTER TABLE customer_address ADD PARTITION P5 VALUES LESS THAN (500);
为范围分区表customer_address增加分区: [500, 600), [600, 700)。 1 ALTER TABLE customer_address ADD PARTITION p6 START(500) END(700) EVERY(100);
为范围分区表customer_address增加MAXVALUE分区p7。 1 ALTER TABLE customer_address ADD PARTITION p7 END(MAXVALUE);
为列表分区表增加分区P6。 1 ALTER TABLE data_list ADD PARTITION P6 VALUES (202302,202303);
split_clause子句用于将一个分区切割成多个分区。 将范围分区表customer_address的P7分区以800为分割点切分。 1 ALTER TABLE customer_address SPLIT PARTITION P7 AT(800) INTO (PARTITION P6a,PARTITION P6b);
将范围分区表customer_address中400所在的分区分割成多个分区。 1 ALTER TABLE customer_address SPLIT PARTITION FOR(400) INTO(PARTITION p_part START(300) END(500) EVERY(100));
将列表分区表data_list的分区P2分割成p2a和p2b两个分区。 1 ALTER TABLE data_list SPLIT PARTITION P2 VALUES(202210) INTO (PARTITION p2a,PARTITION p2b);
exchange_clause子句用于将普通表的数据迁移到指定分区。 如下示例将演示一个普通表math_grade数据迁移到分区表student_grade中分区(math)的操作。 创建分区表student_grade。 1
2
3
4
5
6
7
8
9
10
11
12
13 CREATE TABLE student_grade (
stu_name char(5),
stu_no integer,
grade integer,
subject varchar(30)
)
PARTITION BY LIST(subject)
(
PARTITION gym VALUES('gymnastics'),
PARTITION phys VALUES('physics'),
PARTITION history VALUES('history'),
PARTITION math VALUES('math')
);
插入数据到分区表student_grade中。 1
2
3
4
5
6
7 INSERT INTO student_grade VALUES
('Ann', 20220101, 75, 'gymnastics'),
('Jeck', 20220103, 60, 'math'),
('Anna', 20220108, 56, 'history'),
('Jann', 20220107, 82, 'physics'),
('Molly', 20220104, 91, 'physics'),
('Sam', 20220105, 72, 'math');
查询分区表student_grade的math分区记录。 1 SELECT * FROM student_grade PARTITION (math);
查询结果如下: stu_name | stu_no | grade | subject
----------+----------+-------+---------
Jeck | 20220103 | 60 | math
Sam | 20220105 | 72 | math
(2 rows) 创建一个与分区表student_grade定义匹配的普通表math_grade。 1
2
3
4
5
6
7 CREATE TABLE math_grade
(
stu_name char(5),
stu_no integer,
grade integer,
subject varchar(30)
);
插入数据到表math_grade中。数据与分区表student_grade的math分区的分区规则一致。 1
2
3
4
5 INSERT INTO math_grade VALUES
('Ann', 20220101, 75, 'math'),
('Jeck', 20220103, 60, 'math'),
('Anna', 20220108, 56, 'math'),
('Jann', 20220107, 82, 'math');
将普通表math_grade数据迁移到分区表student_grade的分区(math)。 1 ALTER TABLE student_grade EXCHANGE PARTITION (math) WITH TABLE math_grade;
查询分区表student_grade,结果显示表math_grade中的数据已和分区表student_grade的分区math中的数据交换。 1 SELECT * FROM student_grade PARTITION (math);
1
2
3
4
5
6
7 stu_name | stu_no | grade | subject
----------+----------+-------+---------
Anna | 20220108 | 56 | math
Jeck | 20220103 | 60 | math
Ann | 20220101 | 75 | math
Jann | 20220107 | 82 | math
(4 rows)
查询表math_grade,显示之前存储在分区表student_grade的分区math中的数据已交换到表math_grade中。 1 SELECT * FROM math_grade;
1
2
3
4
5 stu_name | stu_no | grade | subject
----------+----------+-------+---------
Jeck | 20220103 | 60 | math
Sam | 20220105 | 72 | math
(2 rows)
truncate_partitioned_clause子语法用于清理表分区的数据。 清空表customer_address分区p1: 1 ALTER TABLE customer_address TRUNCATE PARTITION p1;
row_clause子句用于设置分区表的行迁移开关。 打开分区表customer_address的迁移开关。 1 ALTER TABLE customer_address ENABLE ROW MOVEMENT;
merge_clause子句用于把多个分区合并成一个分区。 将范围分区表customer_address的P2,P3两个分区合并为一个分区。 1 ALTER TABLE customer_address MERGE PARTITIONS P2, P3 INTO PARTITION P_M;
drop_clause子句用于删除分区表中的指定分区。 删除分区表customer_address的多个分区P6a,P6b。 1 ALTER TABLE customer_address DROP PARTITION P6a, P6b;
-
参数说明 表1 ALTER TABLE PARTITION参数说明 参数 描述 取值范围 table_name 需要修改的分区表的名称。 已存在的分区表名。 partition_name 需要修改的分区名。 已存在的分区名。 partition_value 分区键值。 通过PARTITION FOR ( partition_value [, ...] )子句指定的这一组值,可以唯一确定一个分区。 需要进行重命名分区的分区键的取值范围。 UNUSABLE LOCAL INDEXES 设置该分区上的所有索引不可用。 - REBUILD UNUSABLE LOCAL INDEXES 重建该分区上的所有索引。 - WITHOUT UNUSABLE 重建该分区上的索引时,忽略UNUSABLE状态的索引。 - ENABLE/DISABLE ROW MOVEMENT 行迁移开关。默认是关闭状态。 说明: ENABLE ROW MOVEMENT开启则允许跨分区更新,但此时如果有SELECT FOR UPDATE查询该分区表并发执行,存在查询结果瞬时不一致的可能性,需要谨慎使用。 如果进行UPDATE操作时,更新了元组在分区键上的值,造成了该元组所在分区发生变化,就会根据该开关给出报错信息,或者进行元组在分区间的转移。 ENABLE:打开行迁移开关。 DISABLE:关闭行迁移开关。 ordinary_table_name 进行迁移的普通表的名称。 已存在的普通表名。 { WITH | WITHOUT } VALIDATION 在进行数据迁移时,是否检查普通表中的数据满足指定分区的分区键范围。默认为WITH。 由于检查比较耗时,特别是当数据量很大的情况下更甚。所以在保证当前普通表中的数据满足分区的分区键范围时,可以加上WITHOUT来指明不进行检查。 WITH:对于普通表中的数据要检查是否满足分区的分区键范围,如果有数据不满足,则报错。 WITHOUT:对于普通表中的数据不检查是否满足分区的分区键范围。 VERBOSE 在VALIDATION是WITH状态时,如果检查出普通表有不满足要交换分区的分区键范围的数据,那么把这些数据插入到正确的分区,如果路由不到任何分区,再报错。 须知: 只有在VALIDATION是WITH状态时,才可以指定VERBOSE。 - partition_new_name 分区的新名称。 字符串,需符合标识符命名规范。
-
语法格式 修改表分区主语法。 1
2 ALTER TABLE [ IF EXISTS ] { table_name [*] | ONLY table_name | ONLY ( table_name )}
action [, ... ];
其中action统指如下分区维护子语法。当存在多个分区维护子句时,保证了分区的连续性,无论这些子句的排序如何,
GaussDB (DWS)总会先执行DROP PARTITION再执行ADD PARTITION操作,最后顺序执行其它分区维护操作。 1
2
3
4
5
6
7
8
9
10 modify_clause |
rebuild_clause |
exchange_clause |
row_clause |
merge_clause |
modify_clause |
split_clause |
add_clause |
drop_clause |
truncate_partitioned_clause
modify_clause子语法用于设置分区索引是否可用。 1 MODIFY PARTITION partition_name { UNUSABLE LOCAL INDEXES | REBUILD UNUSABLE LOCAL INDEXES }
rebuild_clause子语法用来重建分区的索引。该语法仅8.3.0.100及以上集群版本支持。 1 REBUILD PARTITION partition_name [ WITHOUT UNUSABLE ]
exchange_clause子语法用于把普通表的数据迁移到指定的分区。 1
2
3 EXCHANGE PARTITION { ( partition_name ) | FOR ( partition_value [, ...] ) }
WITH TABLE {[ ONLY ] ordinary_table_name | ordinary_table_name * | ONLY ( ordinary_table_name )}
[ { WITH | WITHOUT } VALIDATION ] [ VERBOSE ]
进行交换的普通表和分区表必须满足如下条件: 普通表和分区表的列数目相同,对应列的信息严格一致,包括:列名、列的数据类型、列约束、列的Collation信息、列的存储参数、列的压缩信息、已删除字段的数据类型等。 普通表和分区表的表压缩信息严格一致。 普通表和分区表的分布列信息严格一致。 普通表和分区表的索引个数相同,且对应索引的信息严格一致。 普通表和分区表的表约束个数相同,且对应表约束的信息严格一致。 普通表不可以是临时表和unlogged表。 普通表和分区表应该在同一个逻辑集群或节点组(NodeGroup)中,如果不在同一个逻辑集群或节点组,将会采用将数据插入对方表内方式来实现交换分区,这样交换分区的时间与表数据量有关,对于数据量非常大的表和分区表,交换分区将会非常耗时。 在线扩容重分布场景中,如果普通表和分区表正在重分布,交换分区语句有可能中断正在重分布的普通表或分区表(取决于交换分区和重分布语句是否产生锁冲突),通常重分布的普通表或分区表被中断后会重试2次,但同一个表交换分区执行过于频繁可能导致普通表或分区表多次重试重分布都失败。如果普通表重分布过程被交换分区操作打断,在重试重分布时,数据已经被替换为原分区表中的数据,会重新进行全量重分布。 如果行存分区表中最后一个有效字段后的其他字段全部被删除,在不考虑这些删除字段的情况下,分区表与普通表字段信息一致时,分区表和普通表可以进行交换。 列存普通表和列存分区表的表级参数colversion必须一致:禁止colversion2.0与colversion1.0执行交换分区操作。 完成交换后,普通表和分区表的数据被置换,同时普通表和分区表的表空间信息被置换。此时,普通表和分区表的统计信息变得不可靠,需要对普通表和分区表重新执行analyze。 row_clause子语法用于设置分区表的行迁移开关。 1 { ENABLE | DISABLE } ROW MOVEMENT
merge_clause子语法用于把多个分区合并成一个分区。 1 MERGE PARTITIONS { partition_name } [, ...] INTO PARTITION partition_name
INTO关键字前的分区称为源分区,INTO关键字后的分区称为目标分区。 源分区个数不能小于2个。 源分区名称不能重复。 源分区不能存在unusable的索引,否则执行会报错。 目标分区名只能跟最后一个源分区的名称相同,或者跟表的所有分区名都不相同。 目标分区的边界是所有源分区边界的并集。 对于范围分区表,所有的源分区必须是边界连续的分区。 对于列表分区,如果源分区中包含DEFAULT分区,那么目标分区的边界也是DEFAULT。 modify_clause子语法用于设置分区索引是否可用。 1 MODIFY PARTITION partition_name { UNUSABLE LOCAL INDEXES | REBUILD UNUSABLE LOCAL INDEXES }
split_clause子语法用于把一个分区切割成多个分区。 范围分区的split_clause语法如下: 1 SPLIT PARTITION { partition_name | FOR ( partition_value [, ...] ) } { split_point_clause | no_split_point_clause }
指定切割点split_point_clause的语法为: 1 AT ( partition_value ) INTO ( PARTITION partition_name , PARTITION partition_name )
切割点的大小要位于正在被切割分区的分区键范围内,指定切割点的方式只能把一个分区切割成两个新分区。 不指定切割点no_split_point_clause的语法为。 1 INTO { ( partition_less_than_item [, ...] ) | ( partition_start_end_item [, ...] ) }
不指定切割点的方式,partition_less_than_item指定的第一个新分区的分区键要大于正在被切割的分区的前一个分区(如果存在的话)的分区键,partition_less_than_item指定的最后一个分区的分区键要等于正在被切割分区的分区键大小。 不指定切割点的方式,partition_start_end_item指定的第一个新分区的起始点(如果存在的话)必须等于正在被切割的分区的前一个分区(如果存在的话)的分区键,partition_start_end_item指定的最后一个分区的终止点(如果存在的话)必须等于正在被切割分区的分区键。 partition_less_than_item支持的分区键个数最多为4,而partition_start_end_item仅支持1个分区键,其支持的数据类型参见表1中的“PARTITION BY RANGE(partition_key)”参数。 在同一语句中partition_less_than_item和partition_start_end_item两者不可同时使用;不同split语句之间没有限制。 分区项partition_less_than_item的语法为: 1
2 PARTITION partition_name VALUES LESS THAN ( { partition_value | MAXVALUE } [, ...] )
分区项partition_start_end_item的语法为,其约束参见表1中的“partition_start_end_item”参数。 1
2
3
4
5
6 PARTITION partition_name {
{START(partition_value) END (partition_value) EVERY (interval_value)} |
{START(partition_value) END ({partition_value | MAXVALUE})} |
{START(partition_value)} |
{END({partition_value | MAXVALUE})}
}
列表分区的split_clause语法如下: 1 SPLIT PARTITION { partition_name | FOR ( partition_value [, ...] ) } { split_values_clause | split_no_values_clause }
指定切割点的split_values_clause的语法为: 1 VALUES ( { (partition_value) [, ...] } | DEFAULT } ) INTO ( PARTITION partition_name , PARTITION partition_name )
如果源分区不是DEFAULT分区,那么切割点所指定的边界是源分区边界的一个非空真子集;如果源分区是DEFAULT分区,那么切割点所指定的边界不能和其它非DEFAULT分区的边界存在重叠。 切割点的指定的边界是INTO关键字后面的第一个分区的边界,源分区边界与切割点的指定的边界的差集是第二个分区的边界。 当源分区是DEFAULT分区时,第二个分区的边界还是DEFAULT。 不指定切割点的split_no_values_clause的语法为: 1 INTO ( list_partition_item [, ....], PARTITION partition_name )
此处的list_partition_item和创建列表分区表的时候指定分区的语法一样,除了此处的分区定义中边界值不能为DEFAULT。 除了最后一个分区,其他分区需要显式定义边界,定义的边界不能是DEFAULT,并且必须是源分区边界的非空真子集。最后一个分区的边界是源分区边界与其它分区边界的差集,且最后一个分区的边界为空(即差集不能为空集)。 如果源分区是DEFAULT分区,则最后一个分区的边界为DEFAULT。 add_clause子语法用于为指定的分区表添加一个或多个分区。 范围分区的add_clause语法如下: 1 ADD { partition_less_than_item... | partition_start_end_item }
使用partition_less_than_item语法时,分区表必须是范围分区表,否则执行会报错。 此处partition_less_than_item和创建范围分区表的时候指定分区的语法一样。 当前分区表的最后一个分区的边界为MAXVALUE,不允许添加新的分区,否则执行会报错。 列表分区的add_clause语法如下: 1 ADD list_partition_item
使用list_partition_item语法时,分区表必须是列表分区表,否则执行会报错 此处的list_partition_item和创建列表分区表的时候指定分区的语法一样 当前分区表存在DEFAULT分区时,不允许添加新的分区动作,否则执行会报错 drop_clause子语法用于删除分区表中的指定分区。 1 DROP PARTITION { partition_name | FOR ( partition_value [, ...] ) }
drop_clause子语法支持删除多个分区语法。(8.1.3.100及以上集群版本支持。) 1 DROP PARTITION { partition_name [, ... ] }
truncate_partitioned_clause子语法用于清理表分区的数据。 1 TRUNCATE PARTITION { partition_name | FOR ( partition_value [, ...] ) };
partition_value为分区键值。支持指定多个分区键值,多个分区键值以英文逗号分隔。 使用PARTITION FOR子句时,partition_value所在的整个分区会被清空。 修改表分区名称的语法。 1
2 ALTER TABLE [ IF EXISTS ] { table_name [*] | ONLY table_name | ONLY ( table_name )}
RENAME PARTITION { partition_name | FOR ( partition_value [, ...] ) } TO partition_new_name;
-
注意事项 添加分区的名称不能与该分区表已有分区的名称相同。 对于范围分区表,要添加的分区的边界值要和分区表的分区键的类型一致,且要大于分区表的最后一个分区的上边界。 对于列表分区表,如果已经定义DEFAULT分区,则不能添加新分区。 若文档中未特殊注明,则表明范围分区表和列存分区的语法使用相同。 如果目标分区表中已有分区数达到了最大值(32767),则不能继续添加分区。 当分区表只有一个分区时,不能删除该分区。 删除分区(DROP PARTITION)时会连同分区内数据一起删除。 选择分区使用PARTITION FOR(),括号里指定值个数应该与定义分区时使用的列个数相同,并且一一对应。 Value分区表不支持相应的Alter Partition操作。 OBS冷热表对于move,exchange,merge,split操作,不支持指定分区表的表空间为OBS表空间;执行ALTER语法时,需保持分区数据冷热属性不变(即冷分区操作后为冷分区,热分区操作后为热分区),不支持将冷分区数据切至本地表空间;对于冷分区仅支持默认表空间;merge操作不支持将冷分区与热分区进行合并,exchange操作不支持冷分区交换。 避免在业务高峰期执行ALTER TABLE/ALTER TABLE PARTITION(增删改查、DROP PARTITION)、TRUNCATE操作,避免有长SQL阻塞ALTER、TRUNCATE操作或SQL业务被ALTER、TRUNCATE阻塞。 更多开发设计规范参见总体开发设计规范。