【IT168 技术文档】随着数据库应用规模的扩展,需要管理的数据规模也越来越大,普通的数据库查询优化机制在某些情况下已不能满足性能要求了。利用数据库分区技术,可以有效减少I/O量,提升系统查询性能。文章描述了DM(达梦)数据库管理系统垂直分区的实现原理和使用限制,并举例说明了垂直分区的使用,为应用系统的优化提供参考。
1.垂直分区简介
数据库分区是一种物理数据库设计技术,其主要目的是为了在特定的SQL操作中减少数据读¬写的总量以缩减响应时间。垂直分区通过对表的垂直划分来减少目标表的宽度,使某些特定的列被划分到特定的分区,每个分区都包含了其中的列所对应的行。
DM数据库管理系统提供了垂直分区功能,供数据库管理员和应用开发人员使用,以优化系统的性能。本文主要目的是解释DM数据库管理系统垂直分区的实现思路,以及使用限制的说明,供数数据库管理员和应用开发人员参考。
2. DM垂直分区实现说明
DM数据库管理系统中,垂直分区的实现方式是:将垂直分区表分拆成多个表,每个表包含较少的列。定义一个垂直分区表,系统将自动为其创建一个分区基表和若干个分区子表。分区基表不保存实际数据,只保存表定义、分区信息,实际数据保存在分区子表中。
每个分区子表包含定义的分区子表列和CLUSTER PK列。并且,在所有的分区子表上建立了CLUSTER PK索引。这样拆分后,每个子表只包含较少列数据,通过CLUSTER PK列进行行匹配,各个分区子表中的每个逻辑行与其他分区子表的相同逻辑行匹配,可以方便的还原主表定义的完整数据。
2.1 数据修改的实现
分区子表,对用户是透明的,用户操作的对象是分区基表,但实际数据是存放在分区子表中的。因此,系统内部必须将用户对分区基表的数据修改,映射到各个分区子表上。
数据插入,由于分区子表只包含部分列,因此,系统在插入数据过程中,为每个分区子表从输入的分区基表数据中提取出需要的数据,并重新构造符合分区子表格式的记录,插入到每个分区子表。
数据更新,如果被更新列是CLUSTER PK列,那么系统将在所有分区子表中删除对应的数据行,并根据新值构造相应的记录,重新插入分区子表。如果被更新列不是CLUSTER PK列,那么系统首先确定更新列对应的分区子表,并只对相应的分区子表做修改。
数据删除,删除分区基表的一行数据,需要将其所有分区子表上对应的行删除。
2.2 数据还原实现
实现垂直分区表,还要考虑的一个问题是,如何保证垂直分区表的数据完整性和一致性。由于实际数据是存放在各个分区子表中的,基表中并没有任何数据,因此存在一个数据还原的过程――根据分布在不同分区子表中的数据,重新组织出与基表定义一致的数据。
为了还原基表数据,DM数据库管理系统,使用了虚表技术――根据垂直分区表的定义,系统内部为垂直分区基表构造了一个虚表。虚表实现上类似于视图,包含表的列信息、约束信息以及分区信息,还包含类似于视图的查询SQL脚本,对分区子表上的CLUSTER PK列做等值查询,从各个分区子表获取数据,以重新构造出基表的数据行。
2.3 分区指定实现
垂直分区的主要目的是,使查询得以扫描较少的数据,减少I/O量,从而提高查询性能。例如,某个表包含七列,通常只引用该表的前三列,那么将该表的后四列拆分到一个单独的表中将有利于提高查询性能。
一旦查询中使用到垂直分区表,系统判断查询需要的数据是否只涉及某个分区子表,如果是,直接使用分区子表替代分区基表,进行查询优化。系统只需以较少的I/O代价,即可获得需要的数据。如果数据是分布在多个分区子表中,系统使用2.2数据还原实现描述的虚表,替换分区基表,进行查询优化。这样的处理对用户来说是完全透明的。
通过分区指定,系统可自动选择代价较少的查询路径,提高系统性能。
3.DM垂直分区语法说明
DM数据库管理系统通过PARTITON子句提供垂直分区功能,语法式如下:
(<列定义> {,<列定义>} {,<表级完整性约束>})
[]
[<空间限制子句>]
[];
……
::= PARTITION BY
::=
RANGE (<列名>) [LEFT | RIGHT] FOR VALUES ( {,})
| HASH (<列名>) PARTITIONS <分区数> [STORE IN (<文件组列表>)]
| COLUMN ((<列名> {,<列名>}){,(<列名> {,<列名>})})
……
4.DM垂直分区使用限制
垂直分区表的主表不包含实际数据,实际数据存放在垂直分区子表中。对用户来说,垂直分区表和普通表是没有任何区别的,用户可以像使用普通表一样使用垂直分区表。但用户应谨慎考虑垂直分区操作,因为分析多个分区内的数据需要查询连接这些表。如果分区过大的话,可能会影响性能。
同时,垂直分区也不是适合任何应用场景,垂直分区的使用也存在一定的限制,DM垂直分区的使用存在如下限制:
1. 建立垂直分区表必须要有CLUSTER PK,并且此聚集索引不允许删除
2. 除PK列外,其他任何列只能出现在一个分区子表中
3. 包含IDENTITY列的表不允许定义垂直分区
4. 垂直分区表不允许建立触发器
5. 垂直分区表不允许建立CHECK约束
6. 垂直分区子表不允许建立索引
7. 不允许跨分区定义索引
8. 一张表最多允许定义8个垂直分区
9. 由于DM系统中,大数据对象的实现已进行了优化,数据是保存在大数据对象从表中;因此,包含BLOB/CLOB列的表不允许定义垂直分区
5.举例说明
5.1 创建垂直分区表
系统内部将创建3张表,分别是垂直分区基表TT,垂直分区子表TT0DMPART和TT1DMPART。分区子表的命名规则是,在主表名之后附加后缀NDMPART,其中N为0、1、2…。
5.2 查看表定义
调用系统函数TABLEDEF,查看系统创建的3张表定义如下:
CREATE TABLE "TT" AT "SYSTEM"(
"C1" INTEGER NOT NULL,
"C2" INTEGER,
"C3" VARCHAR(100),
"C4" VARCHAR(300),
CLUSTER PRIMARY KEY("C1"))
PARTITION BY COLUMN(("C1", "C2"), ("C1", "C3"))
SELECT TABLEDEF('SYSTEM', 'SYSDBA', 'TT0DMPART');
CREATE TABLE "TT0DMPART" AT "SYSTEM"(
"C1" INTEGER NOT NULL,
"C2" INTEGER,
CLUSTER PRIMARY KEY("C1"))
SELECT TABLEDEF('SYSTEM', 'SYSDBA', 'TT1DMPART');
CREATE TABLE "TT1DMPART" AT "SYSTEM"(
"C1" INTEGER NOT NULL,
"C3" VARCHAR(100),
"C4" VARCHAR(300),
CLUSTER PRIMARY KEY("C1"))
可以看到系统自动创建的分区子表,都包含了CLUSTER PK列C1,C2列位于分区子表TT0DMPART中,而C3,C4列位于分区子表TT1DMPART中。
5.3 查看查询计划
#RSET:[0, 1, 0];
#XNLP:[0, 1, 0]; CROSS_JOIN
#CSEK:[2, 1, 0]; INDEX33560184(TT1DMPART), FULL_SCAN
#CSEK:[0, 0, 0]; INDEX33560183(TT0DMPART), INDEX_EQU_SEARCH
EXPLAIN SELECT C2 FROM TT;
#RSET:[2, 1, 0];
#CSEK:[2, 1, 0]; INDEX33560183(TT0DMPART), FULL_SCAN
EXPLAIN SELECT C2 FROM TT WHERE C1 = 1;
#RSET:[0, 0, 0];
#CSEK:[0, 0, 0]; INDEX33560183(TT0DMPART), INDEX_EQU_SEARCH
分析上述查询计划,可以获知,如果查询列只涉及某个分区子表情况下,系统只需要扫描特定的分区子表数据。由于分区子表中包含的数据比分区前少的多,因此可以极大的减少扫描物理页的数量,从而提升系统性能。
但是,当查询列分布在不同分区子表中,系统需要通过连接查询,从分区子表中获取数据,这将对系统性能产生负面影响。
因此,用户应该根据实际应用情况,科学划分,慎重使用垂直分区来提升系统性能。