注册
初识达梦(七):分区表
专栏/技术分享/ 文章详情 /

初识达梦(七):分区表

刘刘 2025/11/28 128 0 0
摘要
分区的背景

当数据量大时,所有的操作如果都集中在一张表里,效率会很低。但是如果分开数据存放,那么比单笔的效率会高。简单画了个图,如下:
image.png

如图场景,我们共有600w的记录。存在在单表,和分区表。当查询数据时,可以精准定位到某个分区,数据量仅仅时单表的三分之一,效率大家一看就明白了。这就是分区的优势的地方。

达梦数据库关于分区的一些概念

达梦数据库提供了水平分区方式。水平分区包括范围、哈希和列表三种方式。对于水平分区,提供以下分区方式:

  1. 范围(range)水平分区:对表中的某些列上值的范围进行分区,根据某个值的范围,决定将该数据存储在哪个分区上;
  2. 哈希(hash)水平分区:通过指定分区编号来均匀分布数据的一种分区类型,通过在 I/O 设备上进行散列分区,使得这些分区大小基本一致;
  3. 列表(list)水平分区:通过指定表中的某个列的离散值集,来确定应当存储在一起的数据。例如,可以对表上的 status 列的值在(‘A’,‘H’,‘O’)放在一个分区,值在(‘B’,‘I’,‘P’)放在另一个分区,以此类推;
  4. 多级分区表:按上述三种分区方法进行任意组合,将表进行多次分区,称为多级分区表。
分区创建

1、创建范围分区

SQL> create table TR(id int primary key,name char(10)) partition by range ( id ) ( partition p1 values less than (10),partition p2 values less than (20)); 警告: 范围分区未包含MAXVALUE,可能无法定位到分区 操作已执行 已用时间: 15.031(毫秒). 执行号:523. --通过上面的语句提示,可以得到我们应该创建maxvalue分区。如创建语句,那么我们插入值为30时,就无法写入,会报错。 SQL> insert into tr values(30,'abc'); insert into tr values(30,'abc'); [-2731]:没有找到合适的分区. 已用时间: 3.418(毫秒). 执行号:0.

2、创建 LIST 分区表

SQL> create table tl(id int primary key ,name char(10)) partition by list ( name ) ( partition p1 values ('abc','def') ,partition p2 values('qwe'),partition p3 values ( DEFAULT)); 操作已执行 已用时间: 15.022(毫秒). 执行号:527.

3、创建哈希分区表

SQL> create table th(id int primary key ,name char(10)) partition by hash(id) ( partition p1,partition p2); 操作已执行 已用时间: 14.212(毫秒). 执行号:528.

4、创建多级分区表

SQL> CREATE TABLE SALES( 2 SALES_ID INT, 3 SALEMAN CHAR(20), 4 SALEDATE DATETIME, 5 CITY CHAR(10) 6 ) 7 PARTITION BY LIST(CITY) 8 SUBPARTITION BY RANGE(SALEDATE) SUBPARTITION TEMPLATE( 9 SUBPARTITION P11 VALUES LESS THAN ('2012-04-01'), 10 SUBPARTITION P12 VALUES LESS THAN ('2012-07-01'), 11 SUBPARTITION P13 VALUES LESS THAN ('2012-10-01'), 12 SUBPARTITION P14 VALUES EQU OR LESS THAN (MAXVALUE)) 13 ( 14 PARTITION P1 VALUES ('北京', '天津') 15 ( 16 SUBPARTITION P11_1 VALUES LESS THAN ('2012-10-01'), 17 SUBPARTITION P11_2 VALUES EQU OR LESS THAN (MAXVALUE) 18 ), 19 PARTITION P2 VALUES ('上海', '南京', '杭州'), 20 PARTITION P3 VALUES (DEFAULT) 21 ); 操作已执行 已用时间: 29.218(毫秒). 执行号:529.
维护分区表
  1. 创建范围分区时的,警告信息“范围分区未包含MAXVALUE,可能无法定位到分区”。我们该如何解决呢?
    新增分区或者重新建立分区表,但是重建代价太大。所以我们可以通过新增分区来实现。
SQL> 1 2 call sp_tabledef('SYSDBA','TR'); 行号 COLUMN_VALUE ---------- ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 1 CREATE TABLE "SYSDBA"."TR" ( "ID" INT NOT NULL, "NAME" CHAR(10), NOT CLUSTER PRIMARY KEY("ID")) PARTITION BY RANGE("ID") ( PARTITION "P1" VALUES LESS THAN(10) STORAGE(ON "MAIN", CLUSTERBTR) , PARTITION "P2" VALUES LESS THAN(20) STORAGE(ON "MAIN", CLUSTERBTR) ) STORAGE(ON "MAIN", CLUSTERBTR) ; 已用时间: 4.414(毫秒). 执行号:530. SQL> alter table tr add partition p3 values less than ( maxvalue); --新增分区 操作已执行 已用时间: 15.086(毫秒). 执行号:531. SQL> call sp_tabledef('SYSDBA','TR'); 行号 COLUMN_VALUE ---------- ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 1 CREATE TABLE "SYSDBA"."TR" ( "ID" INT NOT NULL, "NAME" CHAR(10), NOT CLUSTER PRIMARY KEY("ID")) PARTITION BY RANGE("ID") ( PARTITION "P1" VALUES LESS THAN(10) STORAGE(ON "MAIN", CLUSTERBTR) , PARTITION "P2" VALUES LESS THAN(20) STORAGE(ON "MAIN", CLUSTERBTR) , PARTITION "P3" VALUES LESS THAN(MAXVALUE) STORAGE(ON "MAIN", CLUSTERBTR) ) STORAGE(ON "MAIN", CLUSTERBTR) ; 已用时间: 2.779(毫秒). 执行号:532. SQL>
  1. 合并分区(只能在范围和 LIST分区上进行合并分区)
SQL> select dbms_metadata.get_ddl('TABLE','TR','SYSDBA'); 行号 DBMS_METADATA.GET_DDL('TABLE','TR','SYSDBA') ---------- ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 1 CREATE TABLE "SYSDBA"."TR" ( "ID" INT NOT NULL, "NAME" CHAR(10), NOT CLUSTER PRIMARY KEY("ID")) PARTITION BY RANGE("ID") ( PARTITION "P1" VALUES LESS THAN(10) STORAGE(ON "MAIN", CLUSTERBTR) , PARTITION "P2" VALUES LESS THAN(20) STORAGE(ON "MAIN", CLUSTERBTR) , PARTITION "P3" VALUES LESS THAN(MAXVALUE) STORAGE(ON "MAIN", CLUSTERBTR) ) STORAGE(ON "MAIN", CLUSTERBTR) ; 已用时间: 5.367(毫秒). 执行号:535. SQL> alter table tr merge partitions p1,p2 into partition p1_2; --partition p1 ,partition p2 merge into p1_2 操作已执行 已用时间: 40.368(毫秒). 执行号:536. SQL> select dbms_metadata.get_ddl('TABLE','TR','SYSDBA'); 行号 DBMS_METADATA.GET_DDL('TABLE','TR','SYSDBA') ---------- ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 1 CREATE TABLE "SYSDBA"."TR" ( "ID" INT NOT NULL, "NAME" CHAR(10), NOT CLUSTER PRIMARY KEY("ID")) PARTITION BY RANGE("ID") ( PARTITION "P1_2" VALUES LESS THAN(20) STORAGE(ON "MAIN", CLUSTERBTR) , PARTITION "P3" VALUES LESS THAN(MAXVALUE) STORAGE(ON "MAIN", CLUSTERBTR) ) STORAGE(ON "MAIN", CLUSTERBTR) ; 已用时间: 4.044(毫秒). 执行号:537.
  1. 交换分区(将分区数据跟普通表数据进行交换,交换的两张表需要具有相同的结构。仅范围分区和 LIST 分区支持交换分区)
SQL> select dbms_metadata.get_ddl('TABLE','TE','SYSDBA'); 行号 DBMS_METADATA.GET_DDL('TABLE','TE','SYSDBA') ---------- ------------------------------------------------------------------------------------------------------------------------------------ 1 CREATE TABLE "SYSDBA"."TE" ( "ID" INT NOT NULL, "NAME" CHAR(10), NOT CLUSTER PRIMARY KEY("ID")) STORAGE(ON "MAIN", CLUSTERBTR) ; 已用时间: 7.306(毫秒). 执行号:577. SQL> select dbms_metadata.get_ddl('TABLE','TR','SYSDBA'); 行号 DBMS_METADATA.GET_DDL('TABLE','TR','SYSDBA') ---------- ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 1 CREATE TABLE "SYSDBA"."TR" ( "ID" INT NOT NULL, "NAME" CHAR(10), NOT CLUSTER PRIMARY KEY("ID")) PARTITION BY RANGE("ID") ( PARTITION "P1" VALUES LESS THAN(10) STORAGE(ON "MAIN", CLUSTERBTR) , PARTITION "P2" VALUES LESS THAN(20) STORAGE(ON "MAIN", CLUSTERBTR) , PARTITION "P3" VALUES LESS THAN(MAXVALUE) STORAGE(ON "MAIN", CLUSTERBTR) ) STORAGE(ON "MAIN", CLUSTERBTR) ; 已用时间: 5.205(毫秒). 执行号:578. SQL> select * from tr; 未选定行 已用时间: 0.346(毫秒). 执行号:579. SQL> select * from te; 行号 ID NAME ---------- ----------- ---------- 1 1 abc 2 2 def 已用时间: 0.281(毫秒). 执行号:580. SQL> alter table tr exchange partition p1 with table te; --交换数据,把分区表tr的p2分区的数据和 te表交换 操作已执行 已用时间: 17.357(毫秒). 执行号:581. SQL> select * from tr; 行号 ID NAME ---------- ----------- ---------- 1 1 abc 2 2 def 已用时间: 6.902(毫秒). 执行号:582. SQL> select * from te; 未选定行 已用时间: 2.381(毫秒). 执行号:583. SQL>
  1. 拆分分区(拆分分区时指定的常量表达式值必须是原范围分区的有效范围值。只能在范围和 LIST 分区上进行拆分分区;)
SQL> select dbms_metadata.get_ddl('TABLE','TR','SYSDBA'); 行号 DBMS_METADATA.GET_DDL('TABLE','TR','SYSDBA') ---------- ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 1 CREATE TABLE "SYSDBA"."TR" ( "ID" INT NOT NULL, "NAME" CHAR(10), NOT CLUSTER PRIMARY KEY("ID")) PARTITION BY RANGE("ID") ( PARTITION "P1_2" VALUES LESS THAN(20) STORAGE(ON "MAIN", CLUSTERBTR) , PARTITION "P3" VALUES LESS THAN(MAXVALUE) STORAGE(ON "MAIN", CLUSTERBTR) ) STORAGE(ON "MAIN", CLUSTERBTR) ; 已用时间: 6.004(毫秒). 执行号:538. SQL> alter table tr split partition p1_2 at (10) into ( partition p1,partition p2 ) ; --拆分分区 p1_2 到 p1,p2. 注意at值,一定是分区的值。比如 这里的10 .。如果是其它值,会报错。 操作已执行 已用时间: 35.006(毫秒). 执行号:539. SQL> select dbms_metadata.get_ddl('TABLE','TR','SYSDBA'); 行号 DBMS_METADATA.GET_DDL('TABLE','TR','SYSDBA') ---------- ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 1 CREATE TABLE "SYSDBA"."TR" ( "ID" INT NOT NULL, "NAME" CHAR(10), NOT CLUSTER PRIMARY KEY("ID")) PARTITION BY RANGE("ID") ( PARTITION "P1" VALUES LESS THAN(10) STORAGE(ON "MAIN", CLUSTERBTR) , PARTITION "P2" VALUES LESS THAN(20) STORAGE(ON "MAIN", CLUSTERBTR) , PARTITION "P3" VALUES LESS THAN(MAXVALUE) STORAGE(ON "MAIN", CLUSTERBTR) ) STORAGE(ON "MAIN", CLUSTERBTR) ; 已用时间: 7.597(毫秒). 执行号:540.
  1. 删除分区
SQL> select dbms_metadata.get_ddl('TABLE','TR','SYSDBA'); 行号 DBMS_METADATA.GET_DDL('TABLE','TR','SYSDBA') ---------- ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 1 CREATE TABLE "SYSDBA"."TR" ( "ID" INT NOT NULL, "NAME" CHAR(10), NOT CLUSTER PRIMARY KEY("ID")) PARTITION BY RANGE("ID") ( PARTITION "P1" VALUES LESS THAN(10) STORAGE(ON "MAIN", CLUSTERBTR) , PARTITION "P2" VALUES LESS THAN(20) STORAGE(ON "MAIN", CLUSTERBTR) , PARTITION "P3" VALUES LESS THAN(MAXVALUE) STORAGE(ON "MAIN", CLUSTERBTR) ) STORAGE(ON "MAIN", CLUSTERBTR) ; 已用时间: 5.437(毫秒). 执行号:584. SQL> alter table tr drop partition p2; 操作已执行 已用时间: 27.208(毫秒). 执行号:585. SQL> select dbms_metadata.get_ddl('TABLE','TR','SYSDBA'); 行号 DBMS_METADATA.GET_DDL('TABLE','TR','SYSDBA') ---------- ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 1 CREATE TABLE "SYSDBA"."TR" ( "ID" INT NOT NULL, "NAME" CHAR(10), NOT CLUSTER PRIMARY KEY("ID")) PARTITION BY RANGE("ID") ( PARTITION "P1" VALUES LESS THAN(10) STORAGE(ON "MAIN", CLUSTERBTR) , PARTITION "P3" VALUES LESS THAN(MAXVALUE) STORAGE(ON "MAIN", CLUSTERBTR) ) STORAGE(ON "MAIN", CLUSTERBTR) ; 已用时间: 5.307(毫秒). 执行号:586.
索引支持

支持局部索引和全局索引。创建语句仅仅区分于关键词“GLOBAL”。全局索引时分区表统一维护的,局部索引是各个分区独立维护。所以当创建UK时,必须包含分区键在内才可以创建成功。

SQL> create index tr_index1 on tr ( name ) global; 操作已执行 已用时间: 38.257(毫秒). 执行号:587. SQL> drop index tr_index1; 操作已执行 已用时间: 19.104(毫秒). 执行号:588. SQL> create index tr_index1 on tr ( name ) ; 操作已执行 已用时间: 24.049(毫秒). 执行号:589. SQL>

以上内容为个人对达梦学习的初步认知,受限于视角与经验,不足之处恳请指正。
以上部分内容来源于官方文档,详细完整内容请移步。

评论
后发表回复

作者

文章

阅读量

获赞

扫一扫
联系客服