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

达梦数据库官方文档中关于分区表和分区索引管理

原创 小小星月明 2022-08-17
2553


1.1 分区的概念
分区是指将表、索引等数据库对象划分为较小的可管理片段的技术,每一个片段称为分区子表或分区索引。一个表被分区后,表的查询操作可以局限于某个分区进行,而不是整个表,这样可以大大提高查询速度。

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

1.2 分区的方法
达梦数据库 DM 支持对表进行水平分区。对于水平分区,提供以下分区方式:
1. 范围(range)水平分区:对表中的某些列上值的范围进行分区,根据某个值的范围,决定将该数据存储在哪个分区上;
2. 哈希(hash)水平分区:通过指定分区编号来均匀分布数据的一种分区类型,通过在 I/O 设备上进行散列分区,使得这些分区大小基本一致;
3. 列表(list)水平分区:通过指定表中的某个列的离散值集,来确定应当存储在一起的数据;
4. 多级分区表:按上述三种分区方区进行任意组合,将表进行多次分区,称为多级分区表。

1.3 创建水平分区表

1.3.1 创建范围分区表

例如,以下语句创建一个范围分区表 callinfo,用来记录用户的 2010 年的电话通讯信息,包括主叫号码、被叫号码、通话时间和时长,并且根据季度进行分区。
CREATE TABLE callinfo(
caller CHAR(15),
callee CHAR(15),
time DATETIME,
duration INT
)
PARTITION BY RANGE(time)(
PARTITION p1 VALUES LESS THAN ('2010-04-01'),
PARTITION p2 VALUES LESS THAN ('2010-07-01'),
PARTITION p3 VALUES LESS THAN ('2010-10-01'),
PARTITION p4 VALUES EQU OR LESS THAN ('2010-12-31') --'2010-12-31'也可替换为 MAXVALUE
);

通过“VALUES EQU OR LESS THAN”指定上界,即该分区包含上界值,如分区 p4 的 time 字段取值范围是['2010-10-01', '2010-12-31']。

SELECT 命令时,可以指定查询某个分区上的数据。例如,以下语句查询 callinfo 表中分区 p1 的数据。
SELECT * FROM callinfo PARTITION (p1);

1.3.2 创建 LIST 分区表
例如,创建一个产品销售记录表 sales,记录产品的销量情况。由于产品只在几个固定的城市销售,所以可以按照销售城市对该表进行分区。
CREATE TABLE sales(
sales_id INT,
saleman CHAR(20),
saledate DATETIME,
city CHAR(10)
)
PARTITION BY LIST(city)(
PARTITION p1 VALUES ('北京', '天津'),
PARTITION p2 VALUES ('上海', '南京', '杭州'),
PARTITION p3 VALUES ('武汉', '长沙'),
PARTITION p4 VALUES ('广州', '深圳')
);

注意的是,LIST 分区的分区键必须唯一。

1.3.3 创建哈希分区表
现在重新考虑产品销售表的例子。如果销售城市不是相对固定的,而是遍布全国各地,这时很难对表进行 LIST 分区。如果为该表进行哈希分区,可以很好地解决这个问题。
CREATE TABLE sales01(
sales_id INT,
saleman CHAR(20),
saledate DATETIME,
city CHAR(10)
)
PARTITION BY HASH(city)(
PARTITION p1,
PARTITION p2,
PARTITION p3,
PARTITION p4
);

如果不需指定分区表名,可以通过指定哈希分区个数来建立哈希分区表。
CREATE TABLE sales02(
sales_id INT,
saleman CHAR(20),
saledate DATETIME,
city CHAR(10)
)
PARTITION BY HASH(city)
PARTITIONS 4 STORE IN (ts1, ts2, ts3, ts4);

PARTITIONS 后的数字表示哈希分区的分区数,STORE IN 子句中指定了哈希分区依次使用的表空间。使用这种方式建立的哈希分区表分区名是匿名的,DM 统一使用DMHASHPART+分区号(从 0 开始)作为分区名。例如,需要查询 sales 第一个分区的数
据,可执行以下语句:
SELECT * FROM sales02 PARTITION (dmhashpart0);

1.3.4 创建多级分区表

例如,创建一个产品销售记录表 sales,记录产品的销量情况。由于产品需要按地点和销售时间进行统计,则可以对该表进行 LIST-RANGE 分区。
DROP TABLE SALES;
CREATE TABLE SALES(
SALES_ID INT,
SALEMAN CHAR(20),
SALEDATE DATETIME,
CITY CHAR(10)
)
PARTITION BY LIST(CITY)
SUBPARTITION BY RANGE(SALEDATE) SUBPARTITION TEMPLATE(
SUBPARTITION P11 VALUES LESS THAN ('2012-04-01'),
SUBPARTITION P12 VALUES LESS THAN ('2012-07-01'),
SUBPARTITION P13 VALUES LESS THAN ('2012-10-01'),
SUBPARTITION P14 VALUES EQU OR LESS THAN (MAXVALUE))
(
PARTITION P1 VALUES ('北京', '天津')
(
SUBPARTITION P11_1 VALUES LESS THAN ('2012-10-01'),
SUBPARTITION P11_2 VALUES EQU OR LESS THAN (MAXVALUE)
),
PARTITION P2 VALUES ('上海', '南京', '杭州'),
PARTITION P3 VALUES (DEFAULT)
);

在创建多级分区表时,指定了子分区模板,同时子分区 P1 自定义了子分区描述 P11_1和 P11_2。P1 有两个子分区 P11_1 和 P11_2。而子分区 P2 和 P3 有四个子分区 P11、P12、
P13 和 P14。
DM 支持最多八层多级分区。

下面给出一个三级分区的例子,更多级别的分区表的建表语句语法类推。
CREATE TABLE STUDENT(NAME VARCHAR(20), AGE INT, SEX VARCHAR(10) CHECK (SEX
IN ('MAIL','FEMAIL')), GRADE INT CHECK (GRADE IN (7,8,9)))
PARTITION BY LIST(GRADE)
SUBPARTITION BY LIST(SEX) SUBPARTITION TEMPLATE
(
SUBPARTITION Q1 VALUES('MAIL'),
SUBPARTITION Q2 VALUES('FEMAIL')
),
SUBPARTITION BY RANGE(AGE) SUBPARTITION TEMPLATE
(
SUBPARTITION R1 VALUES LESS THAN (12),
SUBPARTITION R2 VALUES LESS THAN (15),
SUBPARTITION R3 VALUES LESS THAN (MAXVALUE)
) (
PARTITION P1 VALUES (7),
PARTITION P2 VALUES (8),
PARTITION P3 VALUES (9)
);

1.4 在水平分区表建立索引

DM 支持对水平分区表建立普通索引、唯一索引、聚集索引和函数索引。目前,仅堆表的水平分区表支持 GLOBAL 全局索引。堆表上的 primary key 会自动变为全局索引。
例如,在 sales 表上的 saledate 上建立索引。
CREATE INDEX ind_sales_saldate ON sales(saledate);
CREATE UNIQUE INDEX ind_sales_city ON sales(city);

1.5 维护水平分区表

1.5.1 增加分区
例如,范围分区表 callinfo 现需要记录用户的 2011 年的第一季度的通讯信息,需要为 2011 年第一季度增加一个分区,并将其存储在表空间 ts5 中。
ALTER TABLE callinfo ADD PARTITION p5 VALUES LESS THAN ('2011-4-1') STORAGE (ON ts5);

例如,为 LIST 分区表 sales 添加一个分区管理拉萨和呼和浩特的销售情况。
ALTER TABLE sales ADD PARTITION p5 VALUES ('拉萨', '呼和浩特') STORAGE (ON ts5);

不支持对哈希分区增加分区。

1.5.2 删除分区
例如,范围分区表callinfo 现需要删除记录用户的 2011 年的第一季度的通讯信息,只需删除callinfo 的分区 p1 即可。
ALTER TABLE callinfo DROP PARTITION p1;

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

1.5.3 交换分区

例如,2011 年第二季度已到了,需删除 2010 年第二季度的通话记录,因此,可通过以下脚本来实现:
CREATE TABLE callinfo_2011Q2(
caller CHAR(15),
callee CHAR(15),
time DATETIME,
duration INT
);
--交换分区
ALTER TABLE callinfo EXCHANGE PARTITION p2 WITH TABLE callinfo_2011Q2;

--删除原分区
ALTER TABLE callinfo DROP PARTITION p2;

--新增分区,记录 2011 年第二季度通话记录
ALTER TABLE callinfo ADD PARTITION p6 VALUES LESS THAN ('2011-7-1') STORAGE (ON ts2);

仅范围分区和 LIST 分区支持交换分区。

1.5.4 合并分区

例如,可将 callinfo 的 2010 第 3 季度和第 4 季度合并成一个分区:
ALTER TABLE callinfo MERGE PARTITIONS p3, p4 into partition p3_4;

仅范围分区表支持合并分区,并且合并的分区必须是范围相邻的两分区。导致数据的重组和分区索引的重建,会比较耗时。

1.5.5 拆分分区

例如,将合并后的 p3_4 拆分为原两分区 p3 和 p4,分别记录 2010 年第三和第四季度的通话记录。
ALTER TABLE callinfo SPLIT PARTITION p3_4 AT ('2010-9-30') INTO (PARTITION p3, PARTITION p4);

需要注意的是,仅范围分区表支持拆分分区。导致数据的重组和分区索引的重建,会比较耗时。



1.6 水平分区表的限制

DM 水平分区表有如下限制条件:
1. 分区列类型必须是数值型、字符型或日期型,不支持 BLOB、CLOB、IMAGE、TEXT、LONGVARCHAR、BIT、BINARY、VARBINARY、LONGVARBINARY、时间间隔类型和用户自定义类型为分区列;
2. 范围分区和哈希分区的分区键可以多个,最多不超过 16 列;LIST 分区的分区键必须唯一;
3. 水平分区表指定主键和唯一约束时,分区键必须都包含在主键和唯一约束中;
4. 水平分区表不支持临时表;
5. 不能在水平分区表上建立自引用约束;
6. 普通环境中,水平分区表的各级分区数的总和上限是 65535;MPP 环境下,水平分区表的各级分区总数上限取决于 INI 参数 MAX_EP_SITES,上限为 2 ^( 16 -log2MAX_EP_SITES)。比如:当 MAX_EP_SITES 为默认值 64 时,分区总数上限为 1024;
7. 不允许对分区子表执行任何 DDL 操作;
8. 哈希分区支持重命名、删除约束、设置触发器是否启用的修改操作;
9. 范围分区支持分区合并、拆分、增加、删除、交换、重命名、删除约束、设置触发器是否生效操作;
10. LIST 分区支持分区增加、删除、交换、重命名、删除约束、设置触发器是否生效操作;
11. LIST 分区范围值不能为 NULL;

12. LIST分区子表范围值个数与数据页大小和相关系统表列长度相关,存在以下限制:
1) 4K 页,单个子表最多支持 120 个范围值;
2) 8K 页,单个子表最多支持 254 个范围值;
3) 16K\32K 页,单个子表最多支持 270 个范围值;

13. 对范围分区增加分区值必须是递增的,即只能在最后一个分区后添加分区。LIST分区增加分区值不能存在于其他已存在分区;
14. 当分区数仅剩一个时,不允许删除分区;
15. 仅能对相邻的范围分区进行合并,合并后的分区名可为高分区名或新分区名;
16. 拆分分区的分区值必须在原分区范围中,并且分区名不能跟已有分区名相同;
17. 与分区进行分区交换的普通表,必须与分区表拥有相同的列及索引,但交换分区并不会对数据进行校验,即交换后的数据并不能保证数据完整性,如 CHECK 约束;分区表与普通表创建的索引顺序要求一致;
18. 水平分区表仅支持建立局部索引,不支持建立全局索引,即在分区表上建立索引,每一个表分区都有一个索引分区,并且只索引该分区上的数据,而分区主表上的索引并不索引数据;
19. 不能对水平分区表建立唯一函数索引和全文索引;
20. 不能对分区子表单独建立索引;
21. 在未指定 ENABLE ROW MOVEMENT 的分区表上执行更新分区键,不允许更新后数据发生跨分区的移动,即不能有行迁移;
22. 不能在分区语句的 STORAGE 子句中指定 BRANCH 选项;
23. 不允许引用水平分区子表作为外键约束;
24. 多级分区表最多支持八层;
25. 多级分区表支持下列修改表操作:新增分区、新增列、删除列、删除表级约束、修改表名、设置与删除列的默认值、设置列 NULL 属性、设置列可见性、设置行迁移属性、启用超长记录、with delta、新增子分区、删除子分区、修改二级分区模板信息;
26. 水平分区表支持的列修改操作除了多级分区表支持的操作外,还支持:设置触发器生效/失效、修改列名、修改列属性、增加表级主键约束、删除分区、SPLITE/MERGE分区和交换分区;
27. 水平分区表中包含大字段、自定义字段列,则定义时指定 ENABLE ROW MOVEMENT参数无效,即不允许更新后数据发生跨分区的移动;

28. 间隔分区表的限制说明:
1) 仅支持一级范围分区创建间隔分区;
2) 只能有一个分区列,且分区列类型为日期或数值;
3) 对间隔分区进行 SPLIT,只能在间隔范围内进行操作;
4) 被 SPLIT/MERGE 的分区,其左侧分区不再进行自动创建;
5) 不相邻的间隔的分区,不能 MERGE;
6) 表定义不能包含 MAXVALUE 分区;
7) 不允许新增分区;
8) 不能删除起始间隔分区;
9) 间隔分区表定义语句显示到起始间隔分区为止;
10) 自动生成的间隔分区,均不包含边界值;
11) 间隔表达式只能为常量或 日 期 间隔函数。日期间隔函数为:NUMTOYMINTERVAL、NUMTODSINTERVAL;数值常量可以为整型、DEC 类型;
12) MPP 下不支持间隔分区表。

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论