暂无图片
暂无图片
3
暂无图片
暂无图片
暂无图片

几个开源数据库对比 Oracle 分区表--分区表的维护

原创 张玉龙 2022-04-09
2100

分区表维护支持情况

维护 PGSQL 13.3 OG 2.1 OG 3.0 mysql 8.0 IvorySQL 1.2
增加分区 Y Y Y - Y
删除分区 Y Y Y - Y
截断分区 Y Y Y - Y
合并分区 N Y Y - N
拆分分区 N Y Y - N
交换分区 N Y Y - N
移动分区 Y Y Y - Y
修改分区名称 Y Y Y - Y
  • 备注:
    • openGauss 的交换分区测试失败,不晓得啥原因,看文档是支持交换分区。
    • PostgreSQL and IvorySQL 对虽然不支持交换分区,单是可以通过分区的解绑和绑定来很简单的变相实现。
    • 本文均是测试结果,仅供参考

查询表的分区情况

-- oracle select table_name,partition_name,num_rows,high_value from dba_tab_partitions where table_name='EMP_RANGE_RANGE'; TABLE_NAME PARTITION_NAME NUM_ROWS HIGH_VALUE ----------------- ---------------- ---------- ------------------------------------------------------------------------------------ EMP_RANGE_RANGE HIREDATE_MAX MAXVALUE EMP_RANGE_RANGE HIREDATE_1987 TO_DATE(' 1988-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN') EMP_RANGE_RANGE HIREDATE_1986 TO_DATE(' 1987-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN') EMP_RANGE_RANGE HIREDATE_1985 TO_DATE(' 1986-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN') EMP_RANGE_RANGE HIREDATE_1984 TO_DATE(' 1985-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN') EMP_RANGE_RANGE HIREDATE_1983 TO_DATE(' 1984-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN') EMP_RANGE_RANGE HIREDATE_1982 TO_DATE(' 1983-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN') EMP_RANGE_RANGE HIREDATE_1981 TO_DATE(' 1982-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN') EMP_RANGE_RANGE HIREDATE_1980 TO_DATE(' 1981-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN') EMP_RANGE_RANGE HIREDATE_1979 TO_DATE(' 1980-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN') 10 rows selected. select table_name,partition_name,subpartition_name,num_rows,high_value from dba_tab_subpartitions where table_name='emp_range_range'; TABLE_NAME PARTITION_NAME SUBPARTITION_NAME NUM_ROWS HIGH_VALUE ------------------------------ ------------------------------ ------------------------------ ---------- ----------------- EMP_RANGE_RANGE HIREDATE_1980 HIREDATE_1980_MIN 1000 EMP_RANGE_RANGE HIREDATE_1980 HIREDATE_1980_1000 2000 EMP_RANGE_RANGE HIREDATE_1980 HIREDATE_1980_2000 3000 EMP_RANGE_RANGE HIREDATE_1980 HIREDATE_1980_3000 4000 EMP_RANGE_RANGE HIREDATE_1980 HIREDATE_1980_4000 5000 EMP_RANGE_RANGE HIREDATE_1980 HIREDATE_1980_MAX MAXVALUE ... ... EMP_RANGE_RANGE HIREDATE_1987 HIREDATE_1987_MIN 1000 EMP_RANGE_RANGE HIREDATE_1987 HIREDATE_1987_1000 2000 EMP_RANGE_RANGE HIREDATE_1987 HIREDATE_1987_2000 3000 EMP_RANGE_RANGE HIREDATE_1987 HIREDATE_1987_3000 4000 EMP_RANGE_RANGE HIREDATE_1987 HIREDATE_1987_4000 5000 EMP_RANGE_RANGE HIREDATE_1987 HIREDATE_1987_MAX MAXVALUE EMP_RANGE_RANGE HIREDATE_MAX HIREDATE_MAX_MIN 1000 EMP_RANGE_RANGE HIREDATE_MAX HIREDATE_MAX_1000 2000 EMP_RANGE_RANGE HIREDATE_MAX HIREDATE_MAX_2000 3000 EMP_RANGE_RANGE HIREDATE_MAX HIREDATE_MAX_3000 4000 EMP_RANGE_RANGE HIREDATE_MAX HIREDATE_MAX_4000 5000 EMP_RANGE_RANGE HIREDATE_MAX HIREDATE_MAX_MAX MAXVALUE -- PostgreSQL and IvorySQL \d+ emp_range_range --只能查到一级分区,二级分区需要继续使用 \d+ 查看 postgres=# \d+ emp_range_range Partitioned table "public.emp_range_range" Column | Type | Collation | Nullable | Default | Storage | Stats target | Description ----------+-----------------------+-----------+----------+---------+----------+--------------+------------- empno | numeric(4,0) | | | | main | | ename | character varying(10) | | | | extended | | job | character varying(9) | | | | extended | | mgr | numeric(4,0) | | | | main | | hiredate | date | | | | plain | | sal | numeric(7,2) | | | | main | | comm | numeric(7,2) | | | | main | | deptno | numeric(2,0) | | | | main | | Partition key: RANGE (hiredate) Partitions: emp_range_range_1979 FOR VALUES FROM ('1979-01-01') TO ('1980-01-01'), PARTITIONED, emp_range_range_1980 FOR VALUES FROM ('1980-01-01') TO ('1981-01-01'), PARTITIONED, emp_range_range_1981 FOR VALUES FROM ('1981-01-01') TO ('1982-01-01'), PARTITIONED, emp_range_range_1982 FOR VALUES FROM ('1982-01-01') TO ('1983-01-01'), PARTITIONED, emp_range_range_1983 FOR VALUES FROM ('1983-01-01') TO ('1984-01-01'), PARTITIONED, emp_range_range_1984 FOR VALUES FROM ('1984-01-01') TO ('1985-01-01'), PARTITIONED, emp_range_range_1985 FOR VALUES FROM ('1985-01-01') TO ('1986-01-01'), PARTITIONED, emp_range_range_1986 FOR VALUES FROM ('1986-01-01') TO ('1987-01-01'), PARTITIONED, emp_range_range_1987 FOR VALUES FROM ('1987-01-01') TO ('1988-01-01'), PARTITIONED, emp_range_range_1988 FOR VALUES FROM ('1988-01-01') TO ('1989-01-01'), PARTITIONED, emp_range_range_default DEFAULT, PARTITIONED postgres=# \d+ emp_range_range_1979 Partitioned table "public.emp_range_range_1979" Column | Type | Collation | Nullable | Default | Storage | Stats target | Description ----------+-----------------------+-----------+----------+---------+----------+--------------+------------- empno | numeric(4,0) | | | | main | | ename | character varying(10) | | | | extended | | job | character varying(9) | | | | extended | | mgr | numeric(4,0) | | | | main | | hiredate | date | | | | plain | | sal | numeric(7,2) | | | | main | | comm | numeric(7,2) | | | | main | | deptno | numeric(2,0) | | | | main | | Partition of: emp_range_range FOR VALUES FROM ('1979-01-01') TO ('1980-01-01') Partition constraint: ((hiredate IS NOT NULL) AND (hiredate >= '1979-01-01'::date) AND (hiredate < '1980-01-01'::date)) Partition key: RANGE (sal) Partitions: emp_range_range_1979_1000 FOR VALUES FROM (1000.00) TO (2000.00), emp_range_range_1979_2000 FOR VALUES FROM (2000.00) TO (3000.00), emp_range_range_1979_3000 FOR VALUES FROM (3000.00) TO (4000.00), emp_range_range_1979_4000 FOR VALUES FROM (4000.00) TO (5000.00), emp_range_range_1979_max FOR VALUES FROM (5000.00) TO (MAXVALUE), emp_range_range_1979_min FOR VALUES FROM (MINVALUE) TO (1000.00) -- openGauss \d+ emp_range_range --只能看到分区个数 openGauss=# \d+ emp_range_range Table "public.emp_range_range" Column | Type | Modifiers | Storage | Stats target | Description ----------+--------------------------------+-----------+----------+--------------+------------- empno | numeric(4,0) | | main | | ename | character varying(10) | | extended | | job | character varying(9) | | extended | | mgr | numeric(4,0) | | main | | hiredate | timestamp(0) without time zone | | plain | | sal | numeric(7,2) | | main | | comm | numeric(7,2) | | main | | deptno | numeric(2,0) | | main | | Partition By RANGE(hiredate) Subpartition By RANGE(sal) Number of partitions: 10 (View pg_partition to check each partition range.) Number of subpartitions: 60 (View pg_partition to check each subpartition range.) Has OIDs: no Options: orientation=row, compression=no -- openGauss 的 pg_partition 视图查询一级分区还可以,如果想一次性查询二级分区(subpartition)比较费劲,此时可以使用 compare_tool 工具 openGauss=# select relname,parttype,partstrategy,parentid,boundaries from pg_partition where parentid=(select parentid from pg_partition where relname ='emp_range_range'); relname | parttype | partstrategy | parentid | boundaries -----------+----------+--------------+----------+------------ emp_list | r | l | 25617 | deptno_10 | p | l | 25617 | {10} deptno_20 | p | l | 25617 | {20} deptno_30 | p | l | 25617 | {30}

compare_tool 工具

compare_tool 是一个兼容工具集合,旨在为从其他异构数据库,迁移到 openGauss 之后的系统,创建必要的函数,以及系统视图的兼容。为后续的系统运维与应用改造提供便利。
compare_tool 详情参考:https://gitee.com/enmotech/compat-tools

  • 以下使用 compare_tool 创建 Oracle 兼容视图
tar -xvf compat-tools-v2022.03.23.tar gsql -d postgres -p 1412 -U omm -r -f compat-tools/Oracle_Views.sql gsql -d postgres -p 1412 -U omm -r openGauss=# select table_name,partition_name,subpartition_name,num_rows,high_value from dba_tab_subpartitions where table_name='EMP_RANGE_RANGE'; table_name | partition_name | subpartition_name | num_rows | high_value -----------------+----------------+--------------------+----------+------------ EMP_RANGE_RANGE | HIREDATE_1979 | HIREDATE_1979_MIN | 0 | 1000 EMP_RANGE_RANGE | HIREDATE_1979 | HIREDATE_1979_1000 | 0 | 2000 EMP_RANGE_RANGE | HIREDATE_1979 | HIREDATE_1979_2000 | 0 | 3000 EMP_RANGE_RANGE | HIREDATE_1979 | HIREDATE_1979_3000 | 0 | 4000 EMP_RANGE_RANGE | HIREDATE_1979 | HIREDATE_1979_4000 | 0 | 5000 EMP_RANGE_RANGE | HIREDATE_1979 | HIREDATE_1979_MAX | 0 | MAXVALUE ... ...

删除分区

image.png

-- oracle and openGauss alter table emp_range drop partition hiredate_1979; -- PostgreSQL and IvorySQL 删除子表就是删除分区 drop table emp_range_hiredate_2020;
  • Oracle 和 openGauss 最后一个分区或子分区不允许删除,PostgreSQL and IvorySQL 可以删除最后一个分区或子分区
-- oracle ORA-14083: cannot drop the only partition of a partitioned table ORA-14629: cannot drop the only subpartition of a partition -- openGauss ERROR: Cannot drop the only partition of a partitioned table ERROR: Cannot drop the only subpartition of a partitioned table
  • Oracle 和 openGauss 不允许删除哈希分区表的任何分区或子分区,报错信息如下
-- oracle ORA-14255: table is not partitioned by Range, List, Composite Range or Composite List method ORA-14206: table is not subpartitioned by List or Range methods -- openGauss ERROR: Droping hash partition is unsupported. ERROR: Un-support feature DETAIL: The syntax is unsupported for hash subpartition
  • PostgreSQL 和 IvorySQL 虽然可以删除哈希分区表的分区,但是后续插入的数据还会分配到已经删除的分区中,当发现子分区不存在会报出以下错误信息
postgres=# insert into emp_hash (sal) values (2225); ERROR: no partition of relation "emp_hash" found for row DETAIL: Partition key of the failing row contains (sal) = (2225.00).
  • Oracle 不允许删除间隔分区表手工创建的最后一个分区,报错信息如下
ORA-14758: Last partition in the range section cannot be dropped

解决方法:将间隔分区表转为普通分区表

-- 设置自动分区为普通范围分区 SQL> alter table EMP_INTERVAL set interval(); -- 查看修改后的分区信息 SQL> select table_name,partition_name,num_rows,high_value,interval from dba_tab_partitions where table_name='EMP_INTERVAL'; -- 删除手工创建的分区 SQL> alter table EMP_INTERVAL drop partition SAL_P1; -- 设置普通分区为自动分区 SQL> alter table EMP_INTERVAL set interval(1000);

增加分区

image.png

  • 添加分区的方式
-- oracle and openGauss alter table emp_range add partition hiredate_1988 values less than (to_date('1989-01-01','yyyy-dd-mm')); alter table EMP_LIST add partition DEPTNO_40 values (40); -- PostgreSQL and IvorySQL 创建子表进行增加分区 create table emp_range_hiredate_1989 PARTITION of emp_range FOR VALUES FROM ('1989-01-01 00:00:00+08') TO ('1990-01-01 00:00:00+08'); create table emp_list_deptno_40 partition of emp_list for values in (40);
  • 如果 PostgreSQL 和 IvorySQL 在 RANGE 和 LIST 类型的分区表的 DEFAULT 分区中存在要添加的分区数据时
-- 解绑 Default 分区 ALTER TABLE emp_range DETACH PARTITION emp_range_hiredate_default; -- 创建新分区 create table emp_range_hiredate_2020 PARTITION of emp_range FOR VALUES FROM ('2020-01-01 00:00:00+08') TO ('2021-01-01 00:00:00+08'); -- Default 分区数据转移到 新分区 INSERT INTO emp_range_hiredate_2020 SELECT * FROM emp_range_hiredate_default where hiredate >= ('2020-01-01 00:00:00+08') and hiredate < ('2021-01-01 00:00:00+08'); DELETE FROM emp_range_hiredate_default where hiredate >= ('2020-01-01 00:00:00+08') and hiredate < ('2021-01-01 00:00:00+08'); -- 重新绑定 Default 分区 ALTER TABLE emp_range ATTACH PARTITION emp_range_hiredate_default DEFAULT;
-- 解绑 Default 分区 alter table emp_list detach partition emp_list_deptno_default; -- 创建新分区 create table emp_list_deptno_50 partition of emp_list for values in (50); -- Default 分区数据转移到 新分区 insert into emp_list_deptno_50 select * from emp_list_deptno_default where deptno = 50; delete from emp_list_deptno_default where deptno = 50; -- 重新绑定 Default 分区 alter table emp_list attach partition emp_list_deptno_default default;
  • RANGE 分区表存在 MAXVALUE 时添加分区的报错信息
-- oracle sql> alter table emp_range add partition hiredate_1988 values less than (to_date('1989-01-01','yyyy-dd-mm')); ora-14074: partition bound must collate higher than that of the last partition -- openGauss openGauss=# alter table emp_range add partition hiredate_1988 values less than (to_date('1989-01-01','yyyy-dd-mm')); ERROR: upper boundary of adding partition MUST overtop last existing partition
  • LIST 分区表存在 DEFAULT 时添加分区的报错信息
-- oracle SQL> alter table EMP_LIST add partition DEPTNO_40 values (40); ORA-14323: cannot add partition when DEFAULT partition exists -- openGauss 3.0,openGauss 2.1 不支持 DEFAULT 分区 openGauss=# alter table EMP_LIST add partition DEPTNO_40 values (40); ERROR: list boundary of adding partition MUST NOT overlap with existing partition
  • PostgreSQL 在 RANGE 和 LIST 类型的分区表的 DEFAULT 分区中存在要添加的分区数据时的报错信息
postgres=# insert into emp_range (hiredate) values ('2020-02-02'); postgres=# create table emp_range_hiredate_2020 PARTITION of emp_range FOR VALUES FROM ('2020-01-01 00:00:00+08') TO ('2021-01-01 00:00:00+08'); ERROR: updated partition constraint for default partition "emp_range_hiredate_default" would be violated by some row postgres=# insert into EMP_LIST (deptno) values (50); postgres=# create table emp_list_deptno_50 partition of emp_list for values in (50); ERROR: updated partition constraint for default partition "emp_list_deptno_default" would be violated by some row
  • Oracle 支持为 HASH 分区表添加分区,添加分区完成后会进行数据重分布
SQL> analyze table EMP_HASH compute statistics; SQL> select table_name,partition_name,num_rows,high_value from dba_tab_partitions where table_name='EMP_HASH'; TABLE_NAME PARTITION_NAME NUM_ROWS HIGH_VALUE ------------ ----------------- ---------- ------------ EMP_HASH EMP_HASH_4 4 EMP_HASH EMP_HASH_3 2 EMP_HASH EMP_HASH_2 4 EMP_HASH EMP_HASH_1 4 SQL> alter table emp_hash add partition emp_hash_5; SQL> analyze table EMP_HASH compute statistics; SQL> select table_name,partition_name,num_rows,high_value from dba_tab_partitions where table_name='EMP_HASH'; TABLE_NAME PARTITION_NAME NUM_ROWS HIGH_VALUE ------------ ---------------- ---------- ----------- EMP_HASH EMP_HASH_5 2 EMP_HASH EMP_HASH_4 4 EMP_HASH EMP_HASH_3 2 EMP_HASH EMP_HASH_2 4 EMP_HASH EMP_HASH_1 2
  • openGauss 不支持为 HASH 分区表添加分区
openGauss=# alter table emp_hash add partition emp_hash_5; ERROR: syntax error at or near ";"
  • PostgreSQL and IvorySQL 的 HASH 分区表问题
-- 哈希分区有 MODULUS 总分区个数限制,当分区个数 REMAINDER 达到 MODULUS 上限时不能添加分区 postgres=# create table emp_hash_5 partition of EMP_HASH FOR VALUES WITH (modulus 4, remainder 4); ERROR: remainder for hash partition must be less than modulus -- 如果分区个数与 MODULUS 不相等,则插入数据会存在报错现象, -- PostgreSQL 认为当前表的分区个数与 MODULUS 相等,插入数据时会计算进去,不管真实存在多少个分区。 CREATE TABLE emp_hash (empno NUMERIC(4,0),ename VARCHAR(10),job VARCHAR(9),mgr NUMERIC(4,0),hiredate DATE,sal NUMERIC(7,2),comm NUMERIC(7,2),deptno NUMERIC(2,0)) PARTITION BY HASH (sal); CREATE TABLE emp_hash_1 PARTITION of emp_hash FOR VALUES WITH (MODULUS 6, REMAINDER 0); CREATE TABLE emp_hash_2 PARTITION of emp_hash FOR VALUES WITH (MODULUS 6, REMAINDER 1); CREATE TABLE emp_hash_3 PARTITION of emp_hash FOR VALUES WITH (MODULUS 6, REMAINDER 2); CREATE TABLE emp_hash_4 PARTITION of emp_hash FOR VALUES WITH (MODULUS 6, REMAINDER 3); postgres=# insert into emp_hash select * from emp; ERROR: no partition of relation "emp_hash" found for row DETAIL: Partition key of the failing row contains (sal) = (800.00).
  • INTERVAL 分区表不支持添加分区
SQL> alter table EMP_INTERVAL_DATE_YEAR add partition HIREDATE_P2 values less than (to_date('1978-01-01','yyyy-dd-mm')); ORA-14760: ADD PARTITION is not permitted on Interval partitioned objects openGauss=# alter table EMP_INTERVAL_DATE_YEAR add partition HIREDATE_P2 values less than (to_date('1978-01-01','yyyy-dd-mm')); ERROR: can not add partition against interval partitioned table

截断分区

  • 截断分区的方式
-- oracle and openGauss alter table emp_range truncate partition hiredate_1979; alter table emp_range_range truncate subpartition hiredate_1979_3000; -- PostgreSQL and IvorySQL 创建子表进行 truncate truncate table emp_range_hiredate_1979; truncate table emp_range_range_1979_3000;

合并分区 (Oracle and openGauss)

image.png

  • 合并分区的方式
-- oracle and openGauss -- openGauss 不支持合并 LIST/HASH 分区表,不支持合并组合分区表,不支持合并 subpartition alter table EMP_RANGE merge partitions HIREDATE_1979,HIREDATE_1980 into partition HIREDATE_1980; alter table EMP_RANGE_RANGE merge subpartitions HIREDATE_1980_MIN,HIREDATE_1980_1000 into subpartition HIREDATE_1980_1000; alter table EMP_LIST merge partitions DEPTNO_10,DEPTNO_20 into partition DEPTNO_10_20; alter table EMP_INTERVAL_DATE_YEAR merge partitions SYS_P1,SYS_P2 into partition SYS_P2;
  • openGauss 不支持合并 LIST/HASH 分区表
openGauss=# alter table EMP_LIST merge partitions DEPTNO_10,DEPTNO_20 into partition DEPTNO_10_20; ERROR: can not merge LIST/HASH partition table
  • openGauss 不支持合并组合分区表
openGauss=# alter table EMP_RANGE_RANGE merge partitions HIREDATE_1979,HIREDATE_1980 into partition HIREDATE_1980; ERROR: Un-support feature DETAIL: For subpartition table, merge partitions is not yet supported.
  • openGauss 不支持合并 subpartition
openGauss=# alter table EMP_RANGE_RANGE merge subpartitions HIREDATE_1980_MIN,HIREDATE_1980_1000 into subpartition HIREDATE_1980_1000; ERROR: syntax error at or near "subpartitions" LINE 1: alter table EMP_RANGE_RANGE merge subpartitions HIREDATE_198... ^
  • HASH 分区表不支持合并
-- oracle SQL> alter table EMP_HASH merge partitions EMP_HASH_3,EMP_HASH_4 into partition EMP_HASH_3; ORA-14255: table is not partitioned by Range, List, Composite Range or Composite List method -- openGauss openGauss=# alter table EMP_HASH merge partitions EMP_HASH_3,EMP_HASH_4 into partition EMP_HASH_3; ERROR: can not merge LIST/HASH partition table

拆分分区 (Oracle and openGauss)

image.png

  • 拆分分区的方式
-- oracle alter table emp_range split partition hiredate_1980 at (to_date('01-01-1980','dd-mm-yyyy')) into (partition hiredate_1979,partition hiredate_1980); alter table emp_range split partition HIREDATE_MAX at (to_date('01-01-1989','dd-mm-yyyy')) into (partition hiredate_1988,partition HIREDATE_MAX); alter table emp_list split partition deptno_10_20 values(10) into (partition deptno_10, partition deptno_20); alter table emp_interval split partition sys_p135 at (3000) into (partition emp_interval_3000,partition emp_interval_4000); alter table emp_interval_date_year split partition sys_p138 at (to_date('1981-01-01','yyyy-mm-dd')) into (partition sys_p137,partition sys_p138); alter table emp_range_list split partition hiredate_max at (to_date('1989-01-01','yyyy-mm-dd')) into (partition hiredate_1988,partition hiredate_max); alter table emp_range_list split subpartition HIREDATE_1988_DEPTNO_DEFAULT values(40) into (subpartition HIREDATE_1988_DEPTNO_40,subpartition HIREDATE_1988_DEPTNO_DEFAULT);
  • openGauss 拆分分区,新分区名不能与被拆的分区名相同
openGauss=# alter table emp_range split partition HIREDATE_MAX at (to_date('01-01-1989','dd-mm-yyyy')) into (partition hiredate_1988,partition HIREDATE_MAX); ERROR: resulting partition "hiredate_max" name conflicts with that of an existing partition openGauss=# alter table emp_range split partition HIREDATE_MAX at (to_date('01-01-1989','dd-mm-yyyy')) into (partition hiredate_1988,partition HIREDATE_MAX2); ALTER TABLE
  • openGauss 不支持拆分 LIST 分区
openGauss=# ALTER TABLE EMP_LIST SPLIT PARTITION DEPTNO_10_20 VALUES(10) INTO (PARTITION DEPTNO_10, PARTITION DEPTNO_20); ERROR: syntax error at or near "VALUES" LINE 1: ALTER TABLE EMP_LIST SPLIT PARTITION DEPTNO_10_20 VALUES(10)... ^ openGauss=# ALTER TABLE EMP_LIST SPLIT PARTITION DEPTNO_10_20 AT (10) INTO (PARTITION DEPTNO_10, PARTITION DEPTNO_20); ERROR: can not split LIST/HASH partition table
  • openGauss 不支持拆分组合分区表
openGauss=# alter table emp_range_list split partition hiredate_max at (to_date('1989-01-01','yyyy-mm-dd')) into (partition hiredate_1988,partition hiredate_max); ERROR: Un-support feature DETAIL: For subpartition table, split partition is not supported yet.
  • openGauss 居然支持拆分 subpartition,好意外,而且拆分的子分区还是 LIST 分区,名称还是冲突的,看来对 subpartition 是 LIST 分区有特殊对待?
openGauss=# alter table emp_range_list split subpartition HIREDATE_1987_DEPTNO_DEFAULT values(40) into (subpartition HIREDATE_1987_DEPTNO_40,subpartition HIREDATE_1987_DEPTNO_DEFAULT); ALTER TABLE openGauss=# alter table EMP_RANGE_RANGE split subpartition HIREDATE_1987_MAX at (6000) into (subpartition HIREDATE_1987_5000, subpartition HIREDATE_1987_MAX); ERROR: resulting subpartition "hiredate_1987_max" name conflicts with that of an existing subpartition openGauss=# alter table EMP_RANGE_RANGE split subpartition HIREDATE_1987_MAX at (6000) into (subpartition HIREDATE_1987_5000, subpartition HIREDATE_1987_MAX2); ALTER TABLE

交换分区

image.png

  • Oracle 的分区交换
-- 创建一个空的普通表 SQL> create table hiredate_1981_tt as select * from emp where rownum=0; -- 执行分区交换 SQL> alter table emp_range exchange partition hiredate_1981 with table hiredate_1981_tt; -- 查询交换后的普通表和分区里的数据 SQL> select * from emp_range partition(hiredate_1981); no rows selected SQL> select * from hiredate_1981; EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO ---------- ---------- --------- ---------- ------------------- ---------- ---------- ---------- 7499 ALLEN SALESMAN 7698 1981-02-20 00:00:00 1600 300 30 7521 WARD SALESMAN 7698 1981-02-22 00:00:00 1250 500 30 7566 JONES MANAGER 7839 1981-04-02 00:00:00 2975 20 7654 MARTIN SALESMAN 7698 1981-09-28 00:00:00 1250 1400 30 7698 BLAKE MANAGER 7839 1981-05-01 00:00:00 2850 30 7782 CLARK MANAGER 7839 1981-06-09 00:00:00 2450 10 7839 KING PRESIDENT 1981-11-17 00:00:00 5000 10 7844 TURNER SALESMAN 7698 1981-09-08 00:00:00 1500 0 30 7900 JAMES CLERK 7698 1981-12-03 00:00:00 950 30 7902 FORD ANALYST 7566 1981-12-03 00:00:00 3000 20
  • Oracle 的组合分区交换一级分区
-- 创建一个空的分区表,分区内容为原分区表的二级分区 CREATE TABLE hiredate_1982_tt ( empno NUMBER(4,0) , ename VARCHAR2(10) , job VARCHAR2(9) , mgr NUMBER(4,0) , hiredate DATE , sal NUMBER(7,2) , comm NUMBER(7,2) , deptno NUMBER(2,0) ) PARTITION BY RANGE (sal) (PARTITION hiredate_1982_min VALUES LESS THAN (1000), PARTITION hiredate_1982_1000 VALUES LESS THAN (2000), PARTITION hiredate_1982_2000 VALUES LESS THAN (3000), PARTITION hiredate_1982_3000 VALUES LESS THAN (4000), PARTITION hiredate_1982_4000 VALUES LESS THAN (5000), PARTITION hiredate_1982_max VALUES LESS THAN (MAXVALUE)); -- 执行分区交换 SQL> alter table EMP_RANGE_RANGE exchange partition HIREDATE_1982 with table HIREDATE_1982_tt; -- 查询交换后的普通表和分区里的数据 SQL> select * from HIREDATE_1982_tt; EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO ---------- ---------- --------- ---------- ------------------- ---------- ---------- ---------- 7934 MILLER CLERK 7782 1982-01-23 00:00:00 1300 10
  • Oracle 的组合分区交换一个 SUBPARTITION
-- 创建一个空的普通表 SQL> create table HIREDATE_1981_2000_tt as select * from emp where rownum=0; -- 执行分区交换 SQL> alter table EMP_RANGE_RANGE exchange subpartition HIREDATE_1981_2000 with table HIREDATE_1981_2000_tt; -- 查询交换后的普通表和分区里的数据 SQL> select * from HIREDATE_1981_2000_tt; EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO ---------- ---------- --------- ---------- ------------------- ---------- ---------- ---------- 7566 JONES MANAGER 7839 1981-04-02 00:00:00 2975 20 7698 BLAKE MANAGER 7839 1981-05-01 00:00:00 2850 30 7782 CLARK MANAGER 7839 1981-06-09 00:00:00 2450 10
  • openGauss 上没有测试成功,不晓得啥原因
openGauss=# create table hiredate_1981_tt as select * from emp where rownum=0; INSERT 0 0 openGauss=# alter table emp_range exchange partition hiredate_1981 with table hiredate_1981_tt; ERROR: syntax error at or near "hiredate_1981" LINE 1: alter table emp_range exchange partition hiredate_1981 with ... ^ openGauss=# alter table EMP_RANGE_RANGE exchange subpartition HIREDATE_1981_2000 with table HIREDATE_1981_2000_tt; ERROR: syntax error at or near "subpartition HIREDATE_1981_2000" LINE 1: alter table EMP_RANGE_RANGE exchange subpartition HIREDATE_1... ^
  • PostgreSQL and IvorySQL 的分区交换就是先解绑子表再绑定普通表
-- 创建一个空的普通表 postgres=# create table hiredate_1981_tt as select * from emp limit 0; -- 解绑子表 postgres=# ALTER TABLE emp_range DETACH PARTITION emp_range_hiredate_1981; -- 绑定普通表 postgres=# ALTER TABLE emp_range ATTACH PARTITION hiredate_1981_tt FOR VALUES FROM ('1981-01-01') TO ('1982-01-01'); -- 看心情改名字 ALTER TABLE ... RENAME TO ...;

移动分区

image.png

-- oracle SQL> alter table EMP_RANGE move partition HIREDATE_1987 tablespace users; SQL> alter table EMP_RANGE_RANGE move subpartition HIREDATE_1987_3000 tablespace users; -- openGauss [omm@mysql ~]$ mkdir /home/omm/tbs_users openGauss=# create tablespace tbs_users owner omm location '/home/omm/tbs_users'; openGauss=# alter table EMP_RANGE move partition HIREDATE_1987 tablespace tbs_users; -- PostgreSQL and IvorySQL 就是对表进行移动 [postgres@pgtest2 ~]$ mkdir /home/postgres/tbs_users postgres=# create tablespace tbs_users owner postgres location '/home/postgres/tbs_users'; postgres=# ALTER TABLE emp_range_hiredate_1987 SET TABLESPACE tbs_users;
  • oracle 和 openGauss 不能移动组合分区的一级分区
SQL> alter table EMP_RANGE_RANGE move partition HIREDATE_1987 tablespace users; ORA-14257: cannot move partition other than a Range, List, System, or Hash partition openGauss=# alter table EMP_RANGE_RANGE move partition HIREDATE_1987 tablespace tbs_users; ERROR: Un-support feature DETAIL: For subpartition table, modifying tablespace is not yet supported.
  • openGauss 不能移动 subpartition
openGauss=# alter table EMP_RANGE_RANGE move subpartition HIREDATE_1987_3000 tablespace tbs_users; ERROR: syntax error at or near "subpartition HIREDATE_1987_3000" LINE 1: alter table EMP_RANGE_RANGE move subpartition HIREDATE_1987_... ^

修改分区名称

image.png

-- oracle and openGauss alter table EMP_INTERVAL rename partition SYS_P133 to EMP_INTERVAL_2000; alter table EMP_RANGE_RANGE rename partition HIREDATE_1987 to HIREDATE_1987_2; alter table EMP_RANGE_RANGE rename subpartition HIREDATE_1987_1000 to HIREDATE_1987_1000_2; -- PostgreSQL and IvorySQL 就是修改表名 ALTER TABLE emp_range_hiredate_1983 RENAME TO emp_range_hiredate_1983_2; ALTER TABLE emp_range_range_1983 RENAME TO emp_range_range_1983_2; ALTER TABLE emp_range_range_1983_3000 RENAME TO emp_range_range_1983_3000_2;
  • openGauss 3.0 不支持修改组合分区的一级分区名
openGauss=# alter table EMP_RANGE_RANGE rename partition HIREDATE_1987 to HIREDATE_1987_2; ERROR: Un-support feature DETAIL: For subpartition table, ALTER TABLE ... RENAME PARTITION/SUBPARTITION is not yet supported.
  • openGauss 不支持修改 subpartition 的名称
openGauss=# alter table EMP_RANGE_RANGE rename subpartition HIREDATE_1987_1000 to HIREDATE_1987_1000_2; ERROR: syntax error at or near "HIREDATE_1987_1000" LINE 1: alter table EMP_RANGE_RANGE rename subpartition HIREDATE_198... ^
最后修改时间:2022-04-13 14:18:59
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论