达梦数据库分区表

1 为什么使用分区表?

在大型的企业应用或企业级的数据库应用中,要处理的数据量通常达到 TB 级,对于这样的大型表执行全表扫描或者 DML 操作时,效率是非常低的。

为了提高数据库在大数据量读写操作和查询时的效率,达梦数据库提供了对表和索引进行分区的技术,把表和索引等数据库对象中的数据分割成小的单位,分别存放在一个个单独的段中,用户对表的访问转化为对较小段的访问,以改善大型应用系统的性能。

2 分区的概念

DM 采用子表方式创建分区表,分区表作为分区主表,而每一个分区以一个子表实体存在,即每一个分区都是一个完整的表,一般命名为主表名_分区名。对于水平分区,子表跟主表具有相同的逻辑结构,即分区子表与分区主表有相同的列定义和约束定义。在 DM 分区表中,主表本身不存储数据,所有数据只存储在子表中,从而实现不同分区的完全独立性。水平分区子表删除后,会将子表上的数据一起删除。

由于每一个分区都以一个子表作为实体,那么不同分区可以存储于相同表空间,也可以位于不同的表空间中。将这些分区放在不同的表空间中具有以下的好处:

  1. 减少所有数据都损坏的可能性,一个表空间损坏不影响其他表空间,提高可用性;
  2. 恢复时间大大减少;
  3. 可以将同一个表中的数据分布在不同的磁盘上,从而均衡磁盘上的 I/O 操作;
  4. 提高了表的可管理性、可利用性和访问效率。

分区操作对现存的应用和运行在分区表上的标准 DML 语句来说是透明的。但是,可以通过在 DML 中使用分区子表名字来对应用进行编程,使其充分利用分区的优点。

3 分区表的分类

达梦数据库 DM 支持对表进行水平分区。对于水平分区,提供以下分区方式:

范围(range)水平分区:对表中的某些列上值的范围进行分区,根据某个值的范围,决定将该数据存储在哪个分区上;

列表(list)水平分区:通过指定表中的某个列的离散值集,来确定应当存储在一起的数据。例如,可以对表上的 status 列的值在(‘A’,‘H’,‘O’)放在一个分区,值在(‘B’,‘I’,‘P’)放在另一个分区,以此类推;

哈希(hash)水平分区:通过指定分区编号来均匀分布数据的一种分区类型,通过在 I/O 设备上进行散列分区,使得这些分区大小基本一致;

多级分区表:按上述三种分区方法进行任意组合,将表进行多次分区,称为多级分区表。

4 分区表的优点

由于 DM 划分的分区是相互独立且可以存储于不同的存储介质上的,完全可满足企业高
可用性、均衡 IO、降低维护成本、提高查询性能的要求。

5 范围分区

范围分区是按照某个列或几个列的值的范围来创建分区,当用户向表中写入数据时,数据库服务器将按照这些列上的值进行判断,将数据写入相应的分区中。

在创建范围分区时,首先要指定分区列,即按照哪些列进行分区,然后为每个分区指定数据范围。范围分区支持 MAXVALUE 范围值的使用,MAXVALUE 相当于一个比任何值都大的值。范围分区非常适用于数据按时间范围组织的表,不同的时间段的数据属于不同的分区。

要求:分区列是数字或是日期类型

举例1:

图形化工具创建范围分区表:
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

命令行方式:
create table “TEST”.“T1”
(
“ID” INTEGER,
“NAME” VARCHAR(50)
)
PARTITION BY RANGE (“ID”)
(
PARTITION “P1” VALUES LESS THAN (100), ###p1<100
PARTITION “P2” VALUES LESS THAN (200), ####100<=p2<200
PARTITION “P3” VALUES LESS THAN (300) ####200<=p3<300
)
storage(initial 1, next 1, minextents 1, fillfactor 0)
;

创造数据:

begin
for i in 1..299 loop
insert into test.t1 values(i,'EEEE'||i);
commit;
end loop;
end;

访问分区表:
在这里插入图片描述

insert into test.t1 values(300,'EEEE300');

在这里插入图片描述

alter table test.t1 add partition pn values less than(maxvalue);
insert into test.t1 values(300,'CCC300');
commit;

举例2:

create tablespace TBS1 datafile 'D:\DM8\data\DAMENG\TBS1_01.DBF' SIZE 32;
create tablespace TBS2 datafile 'D:\DM8\data\DAMENG\TBS2_01.DBF' SIZE 32;
create tablespace TBS3 datafile 'D:\DM8\data\DAMENG\TBS3_01.DBF' SIZE 32;
create tablespace TBS4 datafile 'D:\DM8\data\DAMENG\TBS4_01.DBF' SIZE 32;

在这里插入图片描述

create table "TEST"."T2"
(
	"ID" CHAR(10),
	"NAME" VARCHAR2(50)
)
PARTITION BY RANGE ("ID") 
(
PARTITION "P1" VALUES LESS THAN (100) STORAGE( initial 1, next 1, minextents 1, fillfactor 0, on "TBS1"), 
PARTITION "P2" VALUES LESS THAN (200) STORAGE( initial 1, next 1, minextents 1, fillfactor 0, on "TBS2"), 
PARTITION "P3" VALUES LESS THAN (300) STORAGE( initial 1, next 1, minextents 1, fillfactor 0, on "TBS3"), 
PARTITION "PN" VALUES LESS THAN (MAXVALUE) STORAGE( initial 1, next 1, minextents 1, fillfactor 0, on "TBS4")
)
storage(initial 1, next 1, minextents 1, fillfactor 0)
;

举例3:堆表的分区表 需要在同一个表空间

在这里插入图片描述
在这里插入图片描述

create table "TEST"."T3"
(
	"ID" CHAR(10),
	"NAME" VARCHAR2(50)
)
PARTITION BY RANGE ("ID") 
(
PARTITION "P1" VALUES LESS THAN (100) STORAGE( initial 1, next 1, minextents 1, fillfactor 0, on "TEST"), 
PARTITION "P2" VALUES LESS THAN (200) STORAGE( initial 1, next 1, minextents 1, fillfactor 0, on "TEST"), 
PARTITION "P3" VALUES LESS THAN (300) STORAGE( initial 1, next 1, minextents 1, fillfactor 0, on "TEST"), 
PARTITION "P4" VALUES LESS THAN (MAXVALUE) STORAGE( initial 1, next 1, minextents 1, fillfactor 0, on "TEST")
)
storage(initial 1, next 1, minextents 1, fillfactor 0, nobranch,on "TEST") 
;

6 列表分区

范围分区是按照某个列上的数据范围进行分区的,如果某个列上的数据无法通过划分范
围的方法进行分区,并且该列上的数据是相对固定的一些值,可以考虑使用 LIST 分区。一
般来说,对于数字型或者日期型的数据,适合采用范围分区的方法;而对于字符型数据,取
值比较固定的,则适合于采用 LIST 分区的方法。

在创建 LIST 分区时,通过 PARTITION BY LIST 子句指定对表进行 LIST 分区,然后在每
个分区中分区列的取值通过 VALUES 子句指定。当用户向表插入数据时,只要分区列的数
据与 VALUES 子句指定的数据之一相等,该行数据便会写入相应的分区子表中。

LIST 分区的分区键必须唯一。
通过指定表中的某个列的离散值集,来确定应当存储在一起的数据。分区的特点是某列
的值只有几个,基于这样的特点我们可以采用列表分区。

举例:
图形化方式:
在这里插入图片描述
命令行方式:

create table "SYSDBA"."T_SALES"
(
	"SALE_ID" INTEGER,
	"SALEMAN" VARCHAR(50),
	"SALEDATE" DATE,
	"CITY" CHAR(10)
)
PARTITION BY LIST ("CITY") 
(
PARTITION "P1" VALUES ('北京', ' 天津 ',' 哈尔滨','青岛'), 
PARTITION "P2" VALUES ('上海','南京','杭州'), 
PARTITION "P3" VALUES ('武汉','长沙','合肥'), 
PARTITION "P4" VALUES ('广州','深圳','福建')
)
storage(initial 1, next 1, minextents 1, fillfactor 0)
;

添加default分区
LIST 分区支持 DEFAULT 关键字的使用,所有不满足分区条件的数据,都划分为 DEFAULT 的分区,但 DEFAULT 关键字需要用户指定,系统不会自动创建 DEFAULT 分区。

alter table test.t_sales add partition PN values(default);
insert into test.t_sales values(4,'CCCC','2022-04-18','西安');
commit;

7 哈希分区

分区是在列值上使用散列算法,以确定将行放入哪个分区中。当列的值没有合适的条件时,建议使用散列分区。散列分区为通过指定分区编号来均匀分布数据的一种分区类型,因为通过在 I/O 设备上进行散列分区,使得这些分区大小一致。建议分区的数量采用 2 的 n 次方,这样可以使得各个分区间数据分布更加均匀。 将分区列的值进行 hash 运算,然后将数据平均分配各个子分区,存储数据非常快,取数据慢,如果 hash 分区不指定分区表名,那就通过指定的哈希分区数来创建。

分区表名统一使用 ==DMHASHPART+分区号(从 0 开始)==作为分区名。
图形化创建
在这里插入图片描述

命令行创建:

create table "SYSDBA"."T4"
(
	"ID" INTEGER,
	"NAME" CHAR(10)
)
PARTITION BY HASH ("ID") 
(
PARTITION "01", 
PARTITION "02", 
PARTITION "03", 
PARTITION "04"
)
storage(initial 1, next 1, minextents 1, fillfactor 0)
;

当hash分区较多,比如创建16个哈希分区:

create table test.t_hash
(id int, 
name varchar(20)
)
partition by hash (id) 
partitions 16;
<think>好的,我现在要解决用户的问题:达梦数据库分区表如何实现ID自增。首先,我需要回顾达梦数据库的相关知识,特别是分区表和自增字段的实现方式。 用户提到的是分区表,而达梦支持多种分区方式,比如范围分区、列表分区等。自增字段通常是通过IDENTITY属性来实现的,这在达梦中类似于其他数据库的自动递增功能。但是,在分区表中使用自增ID可能会有一些需要注意的地方,比如分区键和自增字段的关系。 首先,我需要确认在达梦数据库中,是否允许在分区表上使用IDENTITY列。根据已有的知识,达梦的IDENTITY列是表级别的自增机制,每个表维护自己的自增序列。因此,在分区表中,每个分区可能共享同一个自增序列,这样插入数据时,无论插入到哪个分区,ID都会连续递增。这一点需要验证,是否有文档说明或者实际测试结果支持。 接下来,考虑具体的实现步骤。用户可能需要创建一个分区表,并指定某个字段为自增主键。例如,创建一个按范围分区的表,其中ID字段是自增的。这时候,创建表的SQL语句应该如何编写?需要确保IDENTITY关键字正确应用,并且分区子句正确设置。 可能的示例代码结构如下: CREATE TABLE 表名 ( ID INT IDENTITY(1,1) PRIMARY KEY, ...其他字段... ) PARTITION BY RANGE (分区键) ( PARTITION p1 VALUES LESS THAN (值), PARTITION p2 VALUES LESS THAN (值), ... ); 这里需要注意,IDENTITY列通常不能作为分区键,因为分区键的值需要明确分配到不同的分区,而自增ID的值是自动生成的,可能导致不可控的分区分配。因此,分区键应该是另一个字段,比如时间字段或其他业务相关的字段。 此外,还需考虑自增ID在分布式系统或高并发插入时的性能问题,虽然这可能超出了当前问题的范围,但作为最佳实践,可能需要提醒用户注意自增字段可能成为性能瓶颈,尤其是在分区较多的情况下。 还需要检查达梦的文档,确认是否有关于分区表自增ID的特殊限制或注意事项。例如,是否每个分区有自己的自增序列,或者全局共享一个。如果是后者,那么插入不同分区时,ID会连续递增,这可能符合用户需求,也可能不符合,需要用户根据业务场景决定。 总结步骤应该是: 1. 创建表时定义ID字段为IDENTITY类型。 2. 指定合适的分区键(非自增字段)。 3. 确保分区策略正确,不影响自增ID的生成。 4. 插入数据测试,验证ID是否按预期自增,并且数据正确分布到各分区。 可能遇到的问题包括:分区键选择不当导致数据分布不均,或者自增ID与分区键的关系不符合业务逻辑。需要提醒用户根据实际需求设计分区策略,并测试验证。</think>在达梦数据库中实现分区表的ID自增,需结合**自增列(IDENTITY)**和**分区表**的特性。以下是分步实现方法: --- ### 一、核心原理 1. **自增列(IDENTITY)**:通过 `IDENTITY(起始值, 步长)` 语法实现字段自动递增。 2. **分区表**:将数据按规则(如范围、列表等)分布到不同物理分区,但逻辑上仍为一张表。 --- ### 二、实现步骤 #### 1. 创建分区表时定义自增列 ```sql -- 示例:按范围分区的自增ID表 CREATE TABLE user_data ( id INT IDENTITY(1,1), -- 自增ID,从1开始,步长1 name VARCHAR(50), create_time DATE, PRIMARY KEY (id, create_time) -- 主键需包含分区键(create_time) ) PARTITION BY RANGE(create_time) ( PARTITION p2023_01 VALUES LESS THAN ('2023-02-01'), PARTITION p2023_02 VALUES LESS THAN ('2023-03-01') ); ``` #### 2. 关键注意事项 - **分区键选择**: - 必须包含分区键字段(如 `create_time`),但自增列(`id`)**不能直接作为分区键**。 - 主键需包含分区键字段(达梦要求)。 - **ID连续性**: - 自增ID是表级全局唯一,跨分区连续递增。例如: - 插入分区 `p2023_01` 生成 `id=1` - 插入分区 `p2023_02` 生成 `id=2` --- ### 三、验证自增效果 ```sql -- 插入数据(无需指定id) INSERT INTO user_data (name, create_time) VALUES ('张三', '2023-01-15'); INSERT INTO user_data (name, create_time) VALUES ('李四', '2023-02-20'); -- 查询结果 SELECT * FROM user_data; ``` 输出: ``` id | name | create_time 1 | 张三 | 2023-01-15 2 | 李四 | 2023-02-20 ``` --- ### 四、扩展场景 #### 1. 分区间自增独立 若需不同分区独立自增ID,需手动管理(如通过计算规则生成ID): ```sql -- 示例:按月份拼接自增ID(如2023010001) CREATE TABLE user_data_custom ( id VARCHAR(20) PRIMARY KEY, name VARCHAR(50), create_time DATE ) PARTITION BY RANGE(create_time) (...); -- 通过触发器或程序生成自定义ID ``` #### 2. 重置自增序列 ```sql -- 修改表的自增列起始值 ALTER TABLE user_data MODIFY id IDENTITY(1000,1); ``` --- ### 五、总结 - **标准方案**:直接使用 `IDENTITY` 属性,适合全局连续ID场景。 - **定制方案**:通过业务逻辑生成ID,满足分区间独立自增需求。 - **性能优化**:分区键应选择高频查询字段(如时间),避免自增ID成为性能瓶颈。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值