分区表类型
openGauss数据库支持这些划分类型:
(1) 范围分区表:指定一个或多个列划分为多个范围,每个范围创建一个分区,用来存储相应的数据。
例如可以采用日期划分范围,将销售数据按照月份进行分区。
(2) 列表分区表:直接按照一个列上的值来划分出分区。例如可以采用销售门店划分销售数据。
(3) 间隔分区表:是一种特殊的范围分区,新增了间隔值定义。当插入记录找不到匹配的分区时可以根据间隔值自动创建分区。
(4) 哈希分区表:根据表的一列,为每个分区指定模数和余数,将要插入表的记录划分到对应的分区中。
范围分区表
RANGE 分区键最大数为16列
CREATE TABLE tp_r16 (
c1 int,
c2 int,
c3 int,
c4 int,
c5 int,
c6 int,
c7 int,
c8 int,
c9 int,
c10 int,
c11 int,
c12 int,
c13 int,
c14 int,
c15 int,
c16 int,
c17 int,
PRIMARY KEY (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16)
)
PARTITION BY RANGE (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16) (
PARTITION p0 VALUES LESS THAN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16),
PARTITION p1 VALUES LESS THAN (2, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16),
PARTITION p2 VALUES LESS THAN (3, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16),
PARTITION p3 VALUES LESS THAN (MAXVALUE, MAXVALUE, MAXVALUE, MAXVALUE, MAXVALUE, MAXVALUE, MAXVALUE, MAXVALUE, MAXVALUE, MAXVALUE, MAXVALUE, MAXVALUE, MAXVALUE, MAXVALUE, MAXVALUE, MAXVALUE)
);
auxdb=# \d+ tp_r16
Table "public.tp_r16"
Column | Type | Modifiers | Storage | Stats target | Description
--------+---------+-----------+---------+--------------+-------------
c1 | integer | not null | plain | |
c2 | integer | not null | plain | |
c3 | integer | not null | plain | |
c4 | integer | not null | plain | |
c5 | integer | not null | plain | |
c6 | integer | not null | plain | |
c7 | integer | not null | plain | |
c8 | integer | not null | plain | |
c9 | integer | not null | plain | |
c10 | integer | not null | plain | |
c11 | integer | not null | plain | |
c12 | integer | not null | plain | |
c13 | integer | not null | plain | |
c14 | integer | not null | plain | |
c15 | integer | not null | plain | |
c16 | integer | not null | plain | |
c17 | integer | | plain | |
Indexes:
"tp_r16_pkey" PRIMARY KEY, btree (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16) LOCAL TABLESPACE pg
_default
Partition By RANGE(c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16)
Number of partitions: 4 (View pg_partition to check each partition range.)
Has OIDs: no
Options: orientation=row, compression=no
1.语法格式
CREATE TABLE partition_table_name
( [column_name data_type ]
[, ... ]
)
PARTITION BY RANGE (partition_key)
(
PARTITION partition_name VALUES LESS THAN (partition_value | MAXVALUE})
[, ... ]
);
2.参数说明
partition_table_name:分区表的名称
column_name:新表中要创建的字段名。
data_type:字段的数据类型。
partition_key:partition_key为分区键的名称。
注:对于从句是VALUE LESS THAN的语法格式,范围分区策略的分区键最多支持4列。
partition_name:partition_name为范围分区的名称。
VALUES LESS THAN:分区中的数值必须小于上边界值。
partition_value:范围分区的上边界,取值依赖于partition_key的类型。
MAXVALUE:表示分区的上边界,它通常用于设置最后一个范围分区的上边界。
3.分区表示例
示例1:创建范围分区表sales_table,含有4个分区,分区键为DATE类型。
分区的范围分别为:
sales_date<2022-04-01,
2022-04-01<= sales_date<2022-07-01,
2022-07-01<=sales_date< 2022-10-01,
2022-10-01 <= sales_date< MAXVALUE
--创建分区表sales_table。
auxdb=# CREATE TABLE sales_table
(
order_no INTEGER NOT NULL,
goods_name CHAR(20) NOT NULL,
sales_date DATE NOT NULL,
sales_volume INTEGER,
sales_store CHAR(20)
)
PARTITION BY RANGE(sales_date)
(
PARTITION season1 VALUES LESS THAN('2022-04-01 00:00:00'),
PARTITION season2 VALUES LESS THAN('2022-07-01 00:00:00'),
PARTITION season3 VALUES LESS THAN('2022-10-01 00:00:00'),
PARTITION season4 VALUES LESS THAN(MAXVALUE)
);
INSERT INTO sales_table VALUES(1, 'jacket', '2022-01-10 00:00:00', 3,'Alaska');
INSERT INTO sales_table VALUES(2, 'hat', '2022-05-06 00:00:00', 5,'Clolorado');
INSERT INTO sales_table VALUES(3, 'shirt', '2022-09-17 00:00:00', 7,'Florida');
INSERT INTO sales_table VALUES(4, 'coat', '2022-10-21 00:00:00', 9,'Hawaii');
--查询sales_table的数据
auxdb=# select * from sales_table;
order_no | goods_name | sales_date | sales_volume | sales_store
----------+----------------------+---------------------+--------------+----------------------
1 | jacket | 2022-01-10 00:00:00 | 3 | Alaska
2 | hat | 2022-05-06 00:00:00 | 5 | Clolorado
2 | hat | 2022-05-06 00:00:00 | 5 | Clolorado
4 | coat | 2022-10-21 00:00:00 | 9 | Hawaii
--查询sales_table的4季度数据
auxdb=# SELECT * FROM sales_table PARTITION (season4);
order_no | goods_name | sales_date | sales_volume | sales_store
----------+----------------------+---------------------+--------------+----------------------
4 | coat | 2022-10-21 00:00:00 | 9 | Hawaii
--查询sales_table的1季度数据
auxdb=# SELECT * FROM sales_table PARTITION FOR ('2021-01-01 00:00:00');
order_no | goods_name | sales_date | sales_volume | sales_store
----------+----------------------+---------------------+--------------+----------------------
1 | jacket | 2022-01-10 00:00:00 | 3 | Alaska
列表分区表
List分区支持16列
create table tp16 (
c1 int,
c2 int,
c3 int,
c4 int,
c5 int,
c6 int,
c7 int,
c8 int,
c9 int,
c10 int,
c11 int,
c12 int,
c13 int,
c14 int,
c15 int,
c16 int
)
partition by list (
c1,
c2,
c3,
c4,
c5,
c6,
c7,
c8,
c9,
c10,
c11,
c12,
c13,
c14,
c15,
c16
)
(
partition p1 values ((1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16)),
partition p2 values ((2,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16)),
partition p3 values ((3,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16)),
partition p4 values ((4,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16)),
partition p5 values ((5,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16)),
partition p6 values ((6,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16)),
partition p7 values ((7,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16)),
partition p8 values ((8,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16)),
partition p9 values ((9,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16)),
partition p10 values ((10,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16)),
partition p11 values ((11,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16)),
partition p12 values ((12,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16)),
partition p13 values ((13,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16)),
partition p14 values ((14,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16)),
partition p15 values ((15,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16)),
partition p16 values ((16,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16))
);
omm=# \d tp16
Table "public.tp16"
Column | Type | Modifiers
--------+---------+-----------
c1 | integer |
c2 | integer |
c3 | integer |
c4 | integer |
c5 | integer |
c6 | integer |
c7 | integer |
c8 | integer |
c9 | integer |
c10 | integer |
c11 | integer |
c12 | integer |
c13 | integer |
c14 | integer |
c15 | integer |
c16 | integer |
Partition By LIST(c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16)
Number of partitions: 16 (View pg_partition to check each partition range.)
1.语法
CREATE TABLE partition_table_name
( [column_name data_type ]
[, ... ]
)
PARTITION BY LIST (partition_key)
(
PARTITION partition_name VALUES (list_values_clause)
[, ... ]
);
list_values_clause:对应分区存在的一个或者多个键值。多个键值之间以逗号分隔。
VALUES (DEFAULT):加入的数据如有“list_values_clause”中未列出的键值,存放在VALUES (DEFAULT)对应的分区。
MAXVALUE:MAXVALUE表示分区的上边界,它通常用于设置最后一个范围分区的上边界。
2.示例:
创建列表分区表graderecord。含有4个分区,分区键为CHAR类型。分区的范围分别为:21.01,21.02,21.03,21.04。
--创建分区表graderecord。
auxdb=# CREATE TABLE graderecord
(
number INTEGER,
name CHAR(20),
class CHAR(20),
grade INTEGER
)
PARTITION BY LIST(class)
(
PARTITION class_01 VALUES ('21.01'),
PARTITION class_02 VALUES ('21.02'),
PARTITION class_03 VALUES ('21.03'),
PARTITION class_04 VALUES ('21.04')
);
-- 数据插入分区。
insert into graderecord values('210101','Alan','21.01',92);
insert into graderecord values('210102','Ben','21.01',62);
insert into graderecord values('210103','Brain','21.01',26);
insert into graderecord values('210204','Carl','21.02',77);
insert into graderecord values('210205','David','21.02',47);
insert into graderecord values('210206','Eric','21.02',97);
insert into graderecord values('210307','Frank','21.03',90);
insert into graderecord values('210308','Gavin','21.03',100);
insert into graderecord values('210309','Henry','21.03',67);
insert into graderecord values('210410','Jack','21.04',75);
insert into graderecord values('210311','Jerry','21.04',60);
--查询graderecord的数据。
auxdb=# SELECT * FROM graderecord;
number | name | class | grade
--------+----------------------+----------------------+-------
210410 | Jack | 21.04 | 75
210311 | Jerry | 21.04 | 60
210307 | Frank | 21.03 | 90
210308 | Gavin | 21.03 | 100
210309 | Henry | 21.03 | 67
210204 | Carl | 21.02 | 77
210205 | David | 21.02 | 47
210206 | Eric | 21.02 | 97
210101 | Alan | 21.01 | 92
210102 | Ben | 21.01 | 62
210103 | Brain | 21.01 | 26
(11 rows)
--查询graderecord的class_01分区数据。
auxdb=# SELECT * FROM graderecord PARTITION (class_01);
number | name | class | grade
--------+----------------------+----------------------+-------
210101 | Alan | 21.01 | 92
210102 | Ben | 21.01 | 62
210103 | Brain | 21.01 | 26
(3 rows)
--查询graderecord的class_04分区数据。
auxdb=# SELECT * FROM graderecord PARTITION (class_04);
number | name | class | grade
--------+----------------------+----------------------+-------
210410 | Jack | 21.04 | 75
210311 | Jerry | 21.04 | 60
(2 rows)
间隔分区表
间隔分区是在范围分区的基础上,增加了间隔值
1.VALUES LESS THAN间隔分区语法格式
CREATE TABLE partition_table_name
( [column_name data_type ]
[, ... ]
)
PARTITION BY RANGE (partition_key)
(
INTERVAL ('interval_expr')
PARTITION partition_name VALUES LESS THAN (partition_value | MAXVALUE})
[, ... ]
);
interval_expr自动创建分区的间隔,例如:自动创建分区的间隔,例如:1 day、1 month。
2.示例:
--创建分区表sales_table。
auxdb=# CREATE TABLE sales_table_int
(
order_no INTEGER NOT NULL,
goods_name CHAR(20) NOT NULL,
sales_date DATE NOT NULL,
sales_volume INTEGER,
sales_store CHAR(20)
)
PARTITION BY RANGE(sales_date)
INTERVAL ('1 month')
(
PARTITION start VALUES LESS THAN('2021-01-01 00:00:00'),
PARTITION later VALUES LESS THAN('2021-01-10 00:00:00')
);
-- 数据插入分区later
auxdb=# INSERT INTO sales_table_int VALUES(1, 'jacket', '2021-01-8 00:00:00', 3,'Alaska');
-- 不在已有分区的数据插入,系统会新建分区sys_p1。
auxdb=# INSERT INTO sales_table_int VALUES(2, 'hat', '2021-04-06 00:00:00', 255,'Clolorado');
-- 不在已有分区的数据插入,系统会新建分区sys_p2。
auxdb=# INSERT INTO sales_table_int VALUES(3, 'shirt', '2021-11-17 00:00:00', 7000,'Florida');
-- 数据插入分区start
auxdb=# INSERT INTO sales_table_int VALUES(4, 'coat', '2020-10-21 00:00:00', 9000,'Hawaii');
auxdb=# \d+ sales_table_int
Table "public.sales_table_int"
Column | Type | Modifiers | Storage | Stats target | Description
--------------+--------------------------------+-----------+----------+--------------+-------------
order_no | integer | not null | plain | |
goods_name | character(20) | not null | extended | |
sales_date | timestamp(0) without time zone | not null | plain | |
sales_volume | integer | | plain | |
sales_store | character(20) | | extended | |
Partition By RANGE(sales_date) INTERVAL('1 month')
Number of partitions: 4 (View pg_partition to check each partition range.)
Has OIDs: no
Options: orientation=row, compression=no
auxdb=# select relname,interval,boundaries from pg_partition ;
relname | interval | boundaries
-----------------+-------------+-------------------------
sales_table | |
season1 | | {"2022-04-01 00:00:00"}
season2 | | {"2022-07-01 00:00:00"}
season3 | | {"2022-10-01 00:00:00"}
season4 | | {NULL}
graderecord | |
class_01 | | {21.01}
class_02 | | {21.02}
class_03 | | {21.03}
class_04 | | {21.04}
sales_table_int | {"1 month"} |
start | | {"2021-01-01 00:00:00"}
later | | {"2021-01-10 00:00:00"}
sys_p1 | | {"2021-04-10 00:00:00"}
sys_p2 | | {"2021-12-10 00:00:00"}
--查询sales_table的数据。
auxdb=# SELECT * FROM sales_table_int;
order_no | goods_name | sales_date | sales_volume | sales_store
----------+----------------------+---------------------+--------------+----------------------
4 | coat | 2020-10-21 00:00:00 | 9000 | Hawaii
1 | jacket | 2021-01-08 00:00:00 | 3 | Alaska
2 | hat | 2021-04-06 00:00:00 | 255 | Clolorado
3 | shirt | 2021-11-17 00:00:00 | 7000 | Florida
(4 rows)
--查询sales_table的start分区数据。这里采用“sales_table_int PARTITION (start);”来引用分区。
auxdb=# SELECT * FROM sales_table_int PARTITION (start);
order_no | goods_name | sales_date | sales_volume | sales_store
----------+----------------------+---------------------+--------------+----------------------
4 | coat | 2020-10-21 00:00:00 | 9000 | Hawaii
(1 row)
--查询sales_table的later分区数据。这里采用“sales_table_int PARTITION (later);”来引用分区。
auxdb=# SELECT * FROM sales_table_int PARTITION (later);
order_no | goods_name | sales_date | sales_volume | sales_store
----------+----------------------+---------------------+--------------+----------------------
1 | jacket | 2021-01-08 00:00:00 | 3 | Alaska
(1 row)
--查询sales_table的sys_p1分区数据。这里采用“sales_table_int PARTITION (sys_p1);”来引用分区。
auxdb=# SELECT * FROM sales_table_int PARTITION (sys_p1);
order_no | goods_name | sales_date | sales_volume | sales_store
----------+----------------------+---------------------+--------------+----------------------
2 | hat | 2021-04-06 00:00:00 | 255 | Clolorado
(1 row)
--查询sales_table的sys_p2分区数据。这里采用“sales_table_int PARTITION (sys_p2);”来引用分区。
auxdb=# SELECT * FROM sales_table_int PARTITION (sys_p2);
order_no | goods_name | sales_date | sales_volume | sales_store
----------+----------------------+---------------------+--------------+----------------------
3 | shirt | 2021-11-17 00:00:00 | 7000 | Florida
(1 row)
INSERT INTO sales_table_int VALUES(5, 'mengwl', '2021-06-17 00:00:00', 8888,'low');
auxdb=# \d+ sales_table_int
Table "public.sales_table_int"
Column | Type | Modifiers | Storage | Stats target | Description
--------------+--------------------------------+-----------+----------+--------------+-------------
order_no | integer | not null | plain | |
goods_name | character(20) | not null | extended | |
sales_date | timestamp(0) without time zone | not null | plain | |
sales_volume | integer | | plain | |
sales_store | character(20) | | extended | |
Partition By RANGE(sales_date) INTERVAL('1 month')
Number of partitions: 5 (View pg_partition to check each partition range.)
Has OIDs: no
Options: orientation=row, compression=no
auxdb=# select relname,interval,boundaries from pg_partition ;
relname | interval | boundaries
-----------------+-------------+-------------------------
sales_table | |
season1 | | {"2022-04-01 00:00:00"}
season2 | | {"2022-07-01 00:00:00"}
season3 | | {"2022-10-01 00:00:00"}
season4 | | {NULL}
graderecord | |
class_01 | | {21.01}
class_02 | | {21.02}
class_03 | | {21.03}
class_04 | | {21.04}
sales_table_int | {"1 month"} |
start | | {"2021-01-01 00:00:00"}
later | | {"2021-01-10 00:00:00"}
sys_p1 | | {"2021-04-10 00:00:00"}
sys_p2 | | {"2021-12-10 00:00:00"}
sys_p3 | | {"2021-07-10 00:00:00"}
(16 rows)
哈希分区表
1.语法
CREATE TABLE partition_table_name
( [column_name data_type ]
[, ... ]
)
PARTITION BY HASH (partition_key)
(PARTITION partition_name )
[, ... ]
);
partition_name:哈希分区的名称。希望创建几个哈希分区就给出几个分区名。
2.创建哈希分区表hash_partition_table
auxdb=# create table hash_partition_table (
col1 int,
col2 int)
partition by hash(col1)
(
partition p1,
partition p2
);
-- 数据插入
INSERT INTO hash_partition_table VALUES(1, 1);
INSERT INTO hash_partition_table VALUES(2, 2);
INSERT INTO hash_partition_table VALUES(3, 3);
INSERT INTO hash_partition_table VALUES(4, 4);
-- 查看数据
auxdb=# select * from hash_partition_table partition (p1);
col1 | col2
------+------
3 | 3
4 | 4
(2 rows)
auxdb=# select * from hash_partition_table partition (p2);
col1 | col2
------+------
1 | 1
2 | 2
(2 rows)
分区表维护
删除分区:
ALTER TABLE partition_table_name DROP PARTITION partition_name;
增加分区:
ALTER TABLE partition_table_name ADD {partition_less_than_item | partition_start_end_item| partition_list_item };
重命名分区:
ALTER TABLE partition_table_name RENAME PARTITION partition_name TO partition_new_name;
分裂分区(指定切割点split_partition_value的语法):
ALTER TABLE partition_table_name SPLIT PARTITION partition_name AT ( split_partition_value ) INTO ( PARTITION partition_new_name1, PARTITION partition_new_name2);
分裂分区(指定分区范围的语法):
ALTER TABLE partition_table_name SPLIT PARTITION partition_name INTO { ( partition_less_than_item [, …] ) | ( partition_start_end_item [, …] ) };
合并分区:
ALTER TABLE partition_table_name MERGE PARTITIONS { partition_name } [, …] INTO PARTITION partition_name;
--创建分区表employees_table。
auxdb=# CREATE TABLE employees_table
(
employee_id INTEGER NOT NULL,
employee_name CHAR(20) NOT NULL,
onboarding_date DATE NOT NULL,
position CHAR(20)
)
PARTITION BY RANGE(onboarding_date)
(
PARTITION founders VALUES LESS THAN('2000-01-01 00:00:00'),
PARTITION senate VALUES LESS THAN('2010-01-01 00:00:00'),
PARTITION seniors VALUES LESS THAN('2020-01-01 00:00:00'),
PARTITION newcomer VALUES LESS THAN(MAXVALUE)
);
-- 插入数据
auxdb=# INSERT INTO employees_table VALUES
(1, 'SMITH', '1997-01-10 00:00:00','Manager'),
(2, 'JONES', '2001-05-06 00:00:00', 'Supervisor'),
(3, 'WILLIAMS', '2011-09-17 00:00:00', 'Engineer'),
(4, 'TAYLOR', '2021-10-21 00:00:00', 'Clerk');
查看newcomer分区
auxdb=# SELECT * FROM employees_table PARTITION (newcomer);
employee_id | employee_name | onboarding_date | position
-------------+----------------------+---------------------+----------------------
4 | TAYLOR | 2021-10-21 00:00:00 | Clerk
(1 row)
--删除newcomer分区。
auxdb=# ALTER TABLE employees_table DROP PARTITION newcomer;
-- 查看newcomer分区数据
auxdb=# select * from employees_table partition (newcomer);
ERROR: partition "newcomer" of relation "employees_table" does not exist
--增加fresh分区。
auxdb=# ALTER TABLE employees_table ADD PARTITION fresh VALUES LESS THAN ('2040-01-01 00:00:00');
ALTER TABLE
--以2030-01-01 00:00:00为分割点,分裂fresh分区为current、future两个分区
auxdb=# ALTER TABLE employees_table SPLIT PARTITION fresh AT ('2030-01-01 00:00:00') INTO (PARTITION current, PARTITION future);
auxdb=# select relname,interval,boundaries from pg_partition ;
relname | interval | boundaries
----------------------+-------------+-------------------------
sales_table | |
season1 | | {"2022-04-01 00:00:00"}
season2 | | {"2022-07-01 00:00:00"}
season3 | | {"2022-10-01 00:00:00"}
season4 | | {NULL}
graderecord | |
class_01 | | {21.01}
class_02 | | {21.02}
class_03 | | {21.03}
class_04 | | {21.04}
sales_table_int | {"1 month"} |
start | | {"2021-01-01 00:00:00"}
later | | {"2021-01-10 00:00:00"}
sys_p1 | | {"2021-04-10 00:00:00"}
sys_p2 | | {"2021-12-10 00:00:00"}
sys_p3 | | {"2021-07-10 00:00:00"}
hash_partition_table | |
p1 | | {0}
p2 | | {1}
employees_table | |
founders | | {"2000-01-01 00:00:00"}
senate | | {"2010-01-01 00:00:00"}
seniors | | {"2020-01-01 00:00:00"}
current | | {"2030-01-01 00:00:00"}
future | | {"2040-01-01 00:00:00"}
(25 rows)
--将分区current改名为now
auxdb=# ALTER TABLE employees_table RENAME PARTITION current TO now;
employees_table | |
founders | | {"2000-01-01 00:00:00"}
senate | | {"2010-01-01 00:00:00"}
seniors | | {"2020-01-01 00:00:00"}
future | | {"2040-01-01 00:00:00"}
now | | {"2030-01-01 00:00:00"}
--将founders,senate合并为一个分区original。
auxdb=# ALTER TABLE employees_table MERGE PARTITIONS founders, senate INTO PARTITION original;
employees_table | |
seniors | | {"2020-01-01 00:00:00"}
future | | {"2040-01-01 00:00:00"}
now | | {"2030-01-01 00:00:00"}
original | | {"2010-01-01 00:00:00"}