达梦分区表

1. 达梦分区类型

        达梦支持对表进行水平分区。分区表作为主表,每个分区以一个子表实体存在,即每个分区都是一个完整的表,因此每个子表都可指定存放的表空间。一般命名为主表明_分区名。对于水平分区,子表跟主表有着相同的逻辑结构。在达梦分区表中,主表本身不存储数据,所有数据只存储在子表中,从而实现不同分区的完全独立性。水平分区子表删除后,会将子表上的数据一起删除。达梦水平分区表提供以下分区方式:

1. 范围水平分区:对表中的某些列上的值的范围进行分区,根据某个值的范围,决定将该数据存储在那个分区。

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

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

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

2. 达梦水平分区表定义

2.1 范围水平分区

CREATE TABLE RANGE_TEST
(
	ID INT,
	NAME VARCHAR(20),
	CONTENT VARCHAR(20),
	STARTTIME DATETIME,
    NOT CLUSTER PRAMARY KEY(ID,STARTTIME)
)
PARTITION BY RANGE(STARTTIME)
(
	PARTITION P1 VALUES LESS THAN(DATETIME'2008-01-01 00:00:00'),
	PARTITION P2 VALUES LESS THAN(DATETIME'2009-01-01 00:00:00'),
	PARTITION PN VALUES EQU OR LESS THAN(MAXVALUE)
);

         进行范围分区时,首先应指定分区列(可多列),格式参考VALUES LESS THAN(无上限)或者VALUES EQU OR LESS THAN(包含上限)。

        范围分区的适用场景为可为数据做出明显的范围划分。如时间、自然数等。

2.2 列表水平分区

CREATE TABLE LIST_TEST
(
	ID INT,
	NAME VARCHAR(20),
	CONTENT VARCHAR(20),
	STARTTIME DATETIME,
    NOT CLUSTER PRAMARY KEY(ID,NAME)
)
PARTITION BY LIST(NAME)
(
	PARTITION P1 VALUES('北京', '上海', '广州','深圳'),
	PARTITION P2 VALUES('成都','绵阳','广元','遂宁'),
	PARTITION P3 VALUES('')
);

        列表分区的适用场景为,当无法确定数据范围时,并且分区列上的值是相对固定的一些值时,可以考虑使用列表分区。如城市名字,书籍类型等。

2.3 哈希水平分区

CREATE TABLE HASH_TEST
(
	ID INT PRIMARY KEY,
	NAME VARCHAR(20),
	CONTENT VARCHAR(20),
	STARTTIME DATETIME
)
PARTITION BY HASH(ID)
(
	PARTITION P1,
	PARTITION P2,
	PARTITION P3
);

        哈希水平分区的适用场景为,既无法确定数据范围,又不是固定的一些值时,可以考虑使用哈希水平分区。如某些加密值,人名等。

3. 水平分区表维护

3.1 增加分区

        列表分区/哈希分区/不含maxvalues的范围分区表增加分区如下:

--range
ALTER TABLE SYSDBA.RANGE_TEST ADD PARTITION P3 VALUES LESS THAN(DATETIME'2010-01-01 00:00:00');
--list
ALTER TABLE SYSDBA.LIST_TEST ADD PARTITION P4 VALUES('西安');
--hash
ALTER TABLE SYSDBA.HASH_TEST ADD PARTITION P4;

 注意事项:

         1). 对于范围分区,如果包含maxvalue分区,则会提示报错:范围分区值非递增。这种情况下可通过以下两种方式新增分区

         2). 对于列表分区,增加分区包含的值不能存在于某个现有分区中

         3). 对于哈希分区的新增,存储选项中的HASHPARTMAP值需为1。(默认为1)

3.1.1 分区拆分

        将maxvalue分区拆分添加的新分区+新的maxvalue分区。语句如下:

--method 1
ALTER TABLE SYSDBA.RANGE_TEST SPLIT PARTITION P4 AT(DATETIME'2010-01-01 00:00:00') INTO(PARTITION P3,PARTITION P5);


--OR LIKE THIS
ALTER TABLE T1 SPLIT PARTITION P3 INTO(PARTITION p7 VALUES LESS 
THAN(25,25),PARTITION p8 VALUES LESS THAN (28,28),PARTITION p9);


ALTER TABLE SYSDBA.RANGE_TEST SPLIT PARTITION P4 INTO(PARTITION P4 VALUES LESS THAN(DATETIME'2011-01-01 00:00:00'),PARTITION P5);

        两种方式的区别在于,第一种无法定义拆分出来的分区边界,而第二种可以。当数据量及业务空闲时,可使用分区拆分的方式将带maxvalue的分区表进行拆分,从而增加水平分区。当数据量过大及业务繁忙时不应使用此方式,此方式涉及数据重组及分区索引重建,耗费较长时间。

3.1.2 分区重构

        针对场景为包含maxvalue分区且maxvalue内包含大量数据(如20亿)的分区表增加分区。实现思路如下:

        1). 新建同分区表同结构的普通临时表,用于存储置换maxvalue分区数据。

        2). 将maxvalue分区同普通临时表进行置换

        3). 删除maxvalue分区

        4). 使用3.1中范围分区增加分区sql语句增加分区

        5). 根据分区列手动整理临时表中数据,针对每个新建分区创建对应临时普通表存放相关数据

        6). 将整理好的临时表同新建分区进行数据置换

        7). 增加maxvalue分区

3.1.3 分区重构实战

        本次样例源自生产环境分区表改造。一张包含35亿数据,maxvalue分区3亿5数据的分区表增加子分区表。

        测试表搭建,表内无数据。原表如上所述,总数据量35一,maxvalue3亿5,maxvalue中数据均为2022年数据,:

CREATE TABLE TEST_PART(
	C1_TIME	DATETIME(6) NOT NULL,
	C2_CODE	NUMBER(5,0) NOT NULL,
	C3_ID	NUMBER(10,0) NOT NULL,
	C4_DATA	NUMBER(9,2),
	NOT CLUSTER PRIMARY KEY(C1_TIME,C3_ID,C2_CODE)
)
PARTITION BY RANGE(C1_TIME)
(
	PARTITION P1 VALUES LESS THAN(DATETIME'2012-01-01 00:00:00'),
	PARTITION P2 VALUES LESS THAN(DATETIME'2013-01-01 00:00:00'),
	PARTITION P3 VALUES LESS THAN(DATETIME'2014-01-01 00:00:00'),
	PARTITION P4 VALUES LESS THAN(DATETIME'2015-01-01 00:00:00'),
	PARTITION P5 VALUES LESS THAN(DATETIME'2016-01-01 00:00:00'),
	PARTITION P6 VALUES LESS THAN(DATETIME'2017-01-01 00:00:00'),
	PARTITION P7 VALUES LESS THAN(DATETIME'2018-01-01 00:00:00'),
	PARTITION P8 VALUES LESS THAN(DATETIME'2019-01-01 00:00:00'),
	PARTITION P9 VALUES LESS THAN(DATETIME'2020-01-01 00:00:00'),
	PARTITION P10 VALUES LESS THAN(DATETIME'2021-01-01 00:00:00'),
    PARTITION P11 VALUES LESS THAN(DATETIME'2022-01-01 00:00:00'),
	PARTITION P12 VALUES EQU OR LESS THAN(MAXVALUE)
);

         分区重构:

        1)数据备份

                根据历史备份时间,在执行操作时间点往前推对应时间进行数据全备用于容灾。

BACKUP DATABASE FULL BACKUPSET 'DB_FULL_BACK_20221228' COMPRESSED LEVEL 2 PARALLEL 2;

        1)暂停相关业务

                方案中因涉及DROP maxvalue分区,因此需关闭相关实时业务,预估耗时5分钟,因业务有缓存,短时内停止不影响数据完整性。

        2)创建临时表TEST_PARTTEMP用于交换maxvalue分区数据

                该临时表表结构需和原分区表保持高度一致。

CREATE TABLE TEST_PARTTEMP(
	C1_TIME	DATETIME(6) NOT NULL,
	C2_CODE	NUMBER(5,0) NOT NULL,
	C3_ID	NUMBER(10,0) NOT NULL,
	C4_DATA	NUMBER(9,2),
	NOT CLUSTER PRIMARY KEY(C1_TIME,C3_ID,C2_CODE)
);

        3)分区置换

                将maxvalue子表同临时表进行数据交换,为DROPmaxvalue分区做准备。

ALTER TABLE TEST_PART EXCHANGE PARTITION P12 WITH TABLE SYSDBA.TEST_PARTTEMP;

        4) 删除maxvalue分区

ALTER TABLE SYSDBA.TEST_PART DROP PARTITION P12;

         5)增加2022-2030子分区

ALTER TABLE SYSDBA.TEST_PART ADD PARTITION P12 VALUES LESS THAN(DATETIME'2023-01-01 00:00:00');
ALTER TABLE SYSDBA.TEST_PART ADD PARTITION P13 VALUES LESS THAN(DATETIME'2024-01-01 00:00:00');
ALTER TABLE SYSDBA.TEST_PART ADD PARTITION P14 VALUES LESS THAN(DATETIME'2025-01-01 00:00:00');
ALTER TABLE SYSDBA.TEST_PART ADD PARTITION P15 VALUES LESS THAN(DATETIME'2026-01-01 00:00:00');
ALTER TABLE SYSDBA.TEST_PART ADD PARTITION P16 VALUES LESS THAN(DATETIME'2027-01-01 00:00:00');
ALTER TABLE SYSDBA.TEST_PART ADD PARTITION P17 VALUES LESS THAN(DATETIME'2028-01-01 00:00:00');
ALTER TABLE SYSDBA.TEST_PART ADD PARTITION P18 VALUES LESS THAN(DATETIME'2029-01-01 00:00:00');
ALTER TABLE SYSDBA.TEST_PART ADD PARTITION P19 VALUES LESS THAN(DATETIME'2030-01-01 00:00:00');

        6)增加maxvalue子分区

ALTER TABLE SYSDBA.TEST_PART ADD PARTITION P20 VALUES EQU OR LESS THAN(MAXVALUE);

        7)临时表数据置换

                因原maxvalue子分区数据只包含2022年数据,因此直接同2022年度子分区进行交换即可。

ALTER TABLE SYSDBA.TEST_PART EXCHANGE PARTITION P12 WITH TABLE SYSDBA.TEST_PARTTEMP;

3.1.4 分区重构实战总结

1.  就实际可操作性而言,针对包含maxvalue的小表增加少量分区,使用拆分分区的方式可行且高效的。但是针对包含maxvalue的大表以及增加大量子分区,使用拆分分区的方式在生产环境应该是不被允许的。之前测试时使用过20亿数据的分区表进行测试。交换分区的方式增加子分区耗时为毫秒级

2. 对于超大的分区表如包含35亿的大分区表,不能使用分区分裂。因为拆分会导致数据重组及重建。而这个表太大了,耗费的时间太久了而且会将相关业务直接卡死。现场应用开始使用方法为拆分分区。执行半小时后发现相关业务直接卡死,撤销后执行分离的manager因为回滚直接卡住。

3. 对于实时性较强的分区表,使用分区重构的方式由于需要DROP maxvalue分区,因此应先暂停相关业务防止发生数据丢失破坏数据完整性。

3.2 删除分区

        范围分区/列表分区删除分区如下:

--range
ALTER TABLE SYSDBA.RANGE_TEST DROP PARTITION PN;
--list
ALTER TABLE SYSDBA.LIST_TEST DROP PARTITION P4;

注意事项:

        哈希分区不支持删除分区。

3.3 交换分区

        范围分区/列表分区交换分区如下:

--TEMP TABLE
CREATE TABLE RANGE_TEST_TEMP
(
	ID INT,
	NAME VARCHAR(20),
	CONTENT VARCHAR(20),
	STARTTIME DATETIME,
	NOT CLUSTER PRIMARY KEY(ID,STARTTIME)
)
--EXCHANGE
ALTER TABLE SYSDBA.RANGE_TEST EXCHANGE PARTITION PN WITH TABLE SYSDBA.RANGE_TEST_TEMP;

注意事项:

        1). 仅范围分区和列表分区支持交换分区,哈希分区不支持。并且交换表同分区表需具备完全一样的结构

        2). 交换分区不会校验数据,不管是否为该分区范围内数据均会写入该分区

        3). 如果包含加密列,对应的加密列要求加密信息完全一致

3.4 合并分区

        范围分区/列表分区合并分区如下:

ALTER TABLE SYSDBA.RANGE_TEST MERGE PARTITIONS P1,P2 INTO PARTITION P1_2;

注意事项:

        1). 仅范围分区和列表分区支持交换分区,哈希分区不支持。且对于范围分区。合并的两个分区需为相邻分区

        2). 仅支持一级子表类型为range/list

        3). 合并多级分区表中的一级子表时,该一级子表下的二级子表及以上层次子表按照级别分别由系统自动合并为一个子表,子表名称为系统内部设置。range类型给你范围值为maxvalue,list类型范围值为default。

        4). 不允许自定义二级及以上层次子表

        5). 不允许直接合并二级及以上层次子表

        6). 合并分区会导致数据重组和分区索引重建,因此对于大分区合并比较耗时

3.5 拆分分区

        范围分区/列表分区拆分分区如下:

--method 1
ALTER TABLE SYSDBA.RANGE_TEST SPLIT PARTITION P4 AT(DATETIME'2010-01-01 00:00:00') INTO(PARTITION P3,PARTITION P5);


ALTER TABLE T1 SPLIT PARTITION P3 INTO(PARTITION p7 VALUES LESS 
THAN(25,25),PARTITION p8 VALUES LESS THAN (28,28),PARTITION p9);

--OR LIKE THIS
ALTER TABLE SYSDBA.RANGE_TEST SPLIT PARTITION P4 INTO(PARTITION P4 VALUES LESS THAN(DATETIME'2011-01-01 00:00:00'),PARTITION P5);

 注意事项:

        1). 仅支持一级子表类型为range/list

        2). 支持拆分为2个及以上个子表

        3). 不允许自定义二级及以上层次子表

        4). 拆分会导致数据重组及重建,因此拆分可能比较耗时

<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成为性能瓶颈。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值