本文首先考察了 DB2 UDB for Linux®、UNIX® 和 Windows® 中的 IBM DB2® Universal Database™ 数据分区功能(Data Partitioning Feature,DPF)在性能和可伸缩性方面的优点。然后,完成在 SUSE Linux Enterprise Server 上安装和配置具有 DPF 功能的 DB2 的步骤。您还将学习到一些重要的概念和设计方面的考虑,这些将帮助您快速掌握 SUSE Linux Enterprise 环境中 DPF 的安装。
接下来的两个图展示了 DPF 真正起作用的情况。图 2 说明了 DPF 被用于三台机器上的情况,其中每台机器上有一个分区。
图 2. 每台机器上一个分区,使用高速通信
注意这里使用的高速通信互连,这可以是各机器之间使用的一个 TCPIP 网络。接下来的
特别要注意,在前面几个图中,对称多处理器(SMP)也可以换成单处理器。但是,在 DPF 环境中 SMP 服务器更为常见。
分区键 由表中的一列或多列组成,用于使用户可以选择如何对他们的数据进行分区。用户可以通过使用数据库分区组和表空间,来确定将表数据分布到哪些数据库分区上。
用户交互通过一个数据库分区,即用于该用户的协调分区(coordinator partition)来进行。协调分区与应用程序运行在同一个数据库分区上,或者,对于远程应用程序,协调分区运行在应用程序所连接的那个数据库分区上。任何数据库分区都可以成为协调分区。
要对一个数据库进行分区,需要 DB2 的 Database Partitioning Feature (DPF) 功能。这种可选的 Database Partition Feature 许可只对 DB2 Enterprise Server Edition (ESE) 可用,其费用按照分区数据库中所使用的 CPU 的数量来计算。
在 instance-owning 机器上设置 NFS 服务器
您需要导出 instance-owner 目录,该目录将被其他数据库分区服务器共享。
- 创建 instance-owner 目录,确保该目录被挂载。使用如下命令:
mkdir /db2homemount /db2home
- 修改 /etc/fstab 中的文件系统表(fstab),使之包括新的文件系统,以便在启动时挂载新的文件系统。条目格式如下:
<device> <mountpoint> <filesystemtype> <options> <dump> <fsckorder>您的条目看上去可能类似于:
清单 1. 示例 instance-owning /etc/fstab 清单
/dev/had7 /db2home ext3 defaults 1 2
该条目使用一个 ext3 文件系统,这种文件系统在 2.4.16 版或更高版本的 Linux 内核中均受支持,文件系统检查(fsck)程序的顺序被设为 2。
设置好 instance-owning 文件系统后,通过在 /etc/exports 文件中添加以下条目,可以在启动时通过一个 NFS 服务导出这个文件系统:
在这种情况下,Database Partition Group 1 横跨除一个数据库分区外的所有数据库分区。它还包含一个名为 'Database Partition Group 2' 的单分区数据库分区组。另外,'Database Partition Group 3' 也与 Database Partition Group 1 共享了一个数据库分区。
可以用 CREATE DATABASE PARTITION GROUP 语句创建新的数据库分区,用 ALTER DATABASE PARTITION GROUP 语句修改数据库分区。
数据被划分到一个数据库分区组中的所有分区上,可以为数据库分区组添加一个或多个数据库分区,或者从中去掉数据库分区。属于数据库系统配置一部分的每个数据库分区都必须在一个名为 db2nodes.cfg 的分区配置文件中定义。一个数据库分区组最多可以包含为数据库系统定义的所有数据库分区。
当创建或修改一个数据库分区组时,就会有一个与之关联的分区映射。数据库管理器可以通过将分区映射与分区键和散列算法相结合,来确定数据库分区组中的哪些数据库分区将存储给定的数据行。在一个非分区数据库中,不需要分区键或分区映射。过一会儿我们将详细讨论这些概念。
一个数据库分区是数据库的一部分,其中具有用户数据、索引、配置文件和事务日志。有一些默认的数据库分区组是在数据库创建时被创建的:
- IBMCATGROUP - 用于包含系统编目的表空间的默认数据库分区组。
- IBMTEMPGROUP - 用于系统临时表空间的默认数据库分区组。
- IBMDEFAULTGROUP - 用于包含用户表的表空间的默认数据库分区组。
用于已声明的临时表的用户临时表空间可以在 IBMDEFAULTGROUP 或任何用户创建的数据库分区组中创建,但不能在 IBMTEMPGROUP 中创建。
为了创建一个新的由 db2nodes.cfg 中所有分区组成的分区组,可以发出以下命令:
create database partition group ALLPART on all dbpartitionnums
如果您想创建一个新的分区组,且这个分区组只包含分区 1 和 2,可以发出如下命令:
create database partition group PART12 on dbpartitionnums (1,2)
可对分区键的对应列的基本数据类型进行比较,并可将它们声明为是分区兼容的(partition compatible)。分区兼容的数据类型具有如下属性:具有相同值但有不同类型的两个变量会按相同的分区算法映射至同一个分区号。 分区兼容性具有下列特征:
- 基本数据类型与另一个相同的基本数据类型兼容。
- 内部格式用于 DATE、TIME 和 TIMESTAMP 数据类型。它们彼此都不兼容,且都不与 CHAR 兼容。
- 分区兼容性不受带有 NOT NULL 或 FOR BIT DATA 定义的列的影响。
- 对兼容数据类型的 NULL 值的处理是完全相同的;对不兼容数据类型的 NULL 值的处理可能不相同。
- 用户定义的类型的基本数据类型用于分析分区兼容性。
- 对分区键中相同值的小数的处理是完全相同的,即使它们的标度和精度不同。
- 字符串中(CHAR、VARCHAR GRAPHIC 或 VARGRAPHIC)的尾部空格会被散列算法忽略。
- BIGINT、SMALLINT 和 INTEGER 是兼容的数据类型。
- REAL 和 FLOAT 是兼容的数据类型。
- 不同长度的 CHAR 和 VARCHAR 是兼容的数据类型。
- GRAPHIC 和 VARGRAPHIC 是兼容的数据类型。
- 分区兼容性不适用于 LONG VARCHAR、LONG VARGRAPHIC、CLOB、DBCLOB 和 BLOB 数据类型,因为它们不能作为分区键。
并置(collocation)是安置同一个数据库分区中包含相关数据的不同表中的行。并置的表使 DB2 可以更有效地使用连接策略。
您可能会发现,作为对特定查询的响应,两个或多个表频繁地提供数据。在此情况下,您会希望这样的表中的相关数据的位置尽可能地靠近。在数据库被物理地划分为两个或多个数据库分区的环境中,必须有一种方法可将划分的表的相关碎片尽可能地靠近。完成此过程的功能称为表并置。
当存取用于连接或子查询的多个表时,DB2(R) 通用数据库(DB2 UDB)能够识别要连接的数据是否位于相同数据库分区上。于是 DB2 就可以在存储数据的数据库分区上执行连接或子查询,而不必在数据库分区之间移动数据。这种局部地执行连接或子查询的能力具有显著的性能优点。
要发生并置,表必须:
- 在相同数据库分区组中,且这个数据库分区组不能处在再分配期间。(在再分配期间,数据库分区组中的表可能使用不同的分区映射 —— 它们不是并置的。)
- 有包含相同数量的列的分区键。
- 分区键的相应列是分区兼容的。
如果一个表在一个单分区数据库分区组中,且该分区组是在另一个表所在的同一个分区上定义的,那么也可以发生并置。
缓冲池是处理期间用于存放数据页和从中读取、修改数据页的一个内存区域。默认情况下,当创建一个缓冲池时,在每个分区上都会创建这样的缓冲池。为了容易管理,通常最好的做法是使每个分区上的缓冲池大小一致。但是,也可以改变特定分区上的缓冲池大小。例如,若要将分区 4 的 'BUF8K' 缓冲池改为 400MB,可以发出命令:
alter bufferpool BUF8K dbpartitionnum 4 size 51200
还可以通过指定一个数据库分区组来选择在哪几个分区上创建缓冲池,在此情况下,只有在数据库分区组中的那些分区上才会创建缓冲池。
表空间是存储数据库对象的容器集合的抽象。表空间在数据库与存储在数据库中的表之间提供了一个间接层。对于每个表空间,在存储设备上都有一个空间与之对应。一个表中的数据、索引、long 字段和 LOB 部分可以存储在相同的表空间中,也可以分别放到不同的表空间中,以提高性能。
当定义一个横跨同一台机器上多个逻辑数据库分区的表空间的容器时,为了避免一个以上的逻辑分区具有相同的路径/设备名称,通常使用数据库分区表达式(Database Partition Expression)。通过使用数据库分区号作为容器名称的一部分,可以确保容器名称在各分区当中是惟一的。这可以作为手动地为每个分区指定位置的替代方法。
可以使用参数 " $N" ([blank]$N) 来表示一个数据库分区表达式,它可以用在容器名称的任何地方,而且可以指定多个数据库分区表达式。数据库分区表达式以一个空格字符结束;数据库分区表达式计算完毕后,空格后的内容附在容器名称的后面。 如果容器名称中在数据库分区表达式后面没有空格字符,则认为剩下的字符串是表达式的一部分。
参数的使用只能以如下一种格式出现(在这个例子中,假设分区号是 5):
| 语法 | 例子 | 值 |
|---|---|---|
| [blank]$N | " $N" | 5 |
| [blank]$N+[number] | " $N+1011" | 1016 |
| [blank]$N%[number] | " $N%3" (% 是模块) | 2 |
| [blank]$N+[number]%[number] | " $N+12%13" | 4 |
| [blank]$N%[number]+[number] | " $N%3+20" | 22 |
如果使用类似于上面的字符串,并且分区号仍然是 5,那么将看到:
| 例子 | 容器名称 |
|---|---|
| '/dbdir/node $N /cont1' | '/dbdir/node5/cont1' |
| '/ $N+1000 /file1' | '/1005/file1' |
| ' $N%10 /container' | '5/container' |
| '/dir/ $N%5+2000 /dmscont' | '/dir/2000/dmscont' |
如果在一个由两个分区组成的数据库上发出以下语句:
CREATE TABLESPACE TBSP1 MANAGED BY DATABASE USING (device '/dev/container $N' 10000)
那么将看到下列容器被创建:
- /dev/container0 - on DATABASE PARTITION 0
- /dev/container1 - on DATABASE PARTITION 1
分区键是用于确定特定一行数据存储在哪个分区的一个列(或一组列)。
分区键是在一个表上用 CREATE TABLE 语句定义的。如果没有提供分区键,则默认地从主键的第一个列创建分区键。如果没有主键,则默认的分区键是表上第一个非 long/非 LOB 型的列。如果没有列能满足作为默认分区键的条件,则表在创建后就没有分区键,也就意味着这个表不能横跨一个以上的分区。
在选择分区键时,应该注意以下几点:
- 表是如何被访问的。
- 查询工作负载的性质。
- 数据库系统所采用的连接策略。
如果不需要特别考虑并置,那么能使数据均匀地散布在数据库分区组中所有数据库分区上的分区键就是好的分区键。在与一个数据库分区组相关联的表空间中,每个表的分区键可以确定表是否是并置的。
不恰当的分区键可能导致数据分布不均匀。具有分布不均匀的数据的列和具有少量 distinct 值的列都不应该被选作分区键。distinct 值的数量必须多到足以确保数据行均匀地分布在数据库分区组中的所有数据库分区上。应用分区散列算法的代价与分区键的规模成比例。分区键不能多于 16 个列,列数越少导致的性能就越好。分区键中不应该包括不必要的列。
在定义分区键时,应考虑以下几点:
- 只包含 long 数据类型(LONG VARCHAR、 LONG VARGRAPHIC、BLOB、CLOB 或 DBCLOB)的多分区的表的创建是不受支持的。
- 分区键的定义不能修改。
- 分区键应该包括最频繁参与连接的列。
- 分区键应该由经常出现在 GROUP 子句中的列组成。
- 任何惟一键或主键都必须包含分区键中的所有列。
- 在在线事务处理(OLTP)环境中,分区键中的所有列出现在事务中时应该使用等号(=)加常量或主机变量。例如,假设在事务中经常用到雇员号 emp_no:
UPDATE emp_table SET ... WHERE emp_no = host-variable在此情况下,EMP_NO 列可以作为 EMP_TABLE 的由单列组成的分区键。
散列分区是用于确定每一行在分区表中的位置的方法。该方法工作原理如下:
- 散列算法应用于分区键的值,产生 0 到 4095 之间的一个分区号。
- 当创建数据库分区组时,同时会创建分区映射。每个分区号按循环的方式顺序地填充分区映射。
- 分区号用作分区映射的索引。分区映射中的号码就是表所在的数据库分区的分区号。
在分区数据库环境中,数据库管理器必须有方法知道表的哪些行存储在哪个数据库分区上,以便发现它需要的数据。数据库管理器使用一个称作分区映射的映射来发现数据。
分区映射是内部生成的数组,对于多分区的数据库分区组,这个数组包含 4,096 个条目,对于单分区的数据库分区组,这个数组只包含一个条目。
对于单分区的数据库分区组,分区映射只有一个条目,其中包含数据库表中所有的行所在的数据库分区的分区号。对于多分区数据库分区组,数据库分区组中的分区号是以循环的方式指定的。就像城市地图按网格分成一些区一样,数据库管理器使用分区键来确定数据所存储在的位置(数据库分区)。
例如,假设您在 5 个数据库分区(分区号为 0-4)上有一个数据库。那么,这个数据库的 IBMDEFAULTGROUP 数据库分区组的分区映射为:
0 1 2 3 4 0 1 2 3 4 0 1 2...
如果在使用数据库分区 1 和 2 的数据库中创建了一个数据库分区组,那么这个数据库分区组的分区映射为:
1 2 1 2 1 2 1 2...
如果数据库中所装载的表的分区键是 1 到 500,000 之间的整数,则分区键被散列到 0 到 4 095 之间的一个分区号。这个号码将用于作为分区映射的一个索引,以选择那一行所在的数据库分区。
分区映射是在分区数据库中控制数据存储位置的一种灵活的方式。另外还有一种再分配(redistribution)实用程序,通过它可以改变数据在数据库中的数据库分区上的分布(使之平衡或偏斜),不过这超出了本文的范围。
DB2NODE 环境变量用于指定想要连接到的目标逻辑分区。如果没有设置该变量,那么它将默认地等于用机器上的端口 0 定义的那个分区(在 db2nodes.cfg 文件中)。
如果要连接到逻辑分区 2,那么可以输入以下命令:
DB2NODE=2export DB2NODEdb2 terminate
为了确保更改生效,必须用 terminate 命令。
为了识别当前活动逻辑节点,可以发出以下命令:
db2 "values (current dbpartitionnum)"
这两个工具使跨所有机器或所有分区执行命令变得容易。两个工具使用相同的一组有用的选项,这些选项可以在 DB2 Command Window 中通过 "rah ?" 或 "db2_all ?" 命令显示出来。
db2_all
db2_all 用于在所有指定的分区上运行命令。
db2_all ";db2 update db cfg for SAMPLE using NEWLOGPATH /db2_db/logs"
分号用于作为一个前缀,表明该命令将在各分区上并发地运行。
rah
rah 用于在组成分区环境的所有机器上运行一个命令。
当执行离线数据库备份时,需要单独备份编目分区。但是,在线备份时就不需要这样,因为日志是包括在备份镜像中的。例如,我们有一个名为 sample 的数据库和一个 /dev/backup 目录,从所有分区那里都可以访问这个目录。
首先需要备份位于分区 0 上的编目分区,这里只需指定 "<<+0<"" (在这个例子中)
db2_all '<<+0< db2 BACKUP DATABASE sample TO /dev/backup'
接着备份其他分区(除了分区 0),方法是指定 "<<-0<":
db2_all '|<<-0< db2 BACKUP DATABASE sample TO /dev/backup'
注意,前缀 "|" 将导致依次运行 BACKUP 命令。现在,在 /dev/backup 目录中可以找到每个分区的备份镜像。
DBPARTITIONNUM 函数可用于确定一个行所在的分区。例如,如果用在一个 SELECT 子句中,那么该函数将返回表中组成 SELECT 语句结果的每一行的分区号。
该函数的参数必须是一个表中某一列的全限定或非限定列名。结果的数据类型是 INTEGER,并且不会为 null。由于只返回行这一级的信息,所以不管指定表的哪一列,结果总是相同的。如果没有 db2nodes.cfg 文件,则结果为 0。
例如:
select lastname, dbpartitionnum(lastname) as part_num from employee order by 1
清单 7. 使用 dbpartitionnum 函数的结果集
|
节点(node)目录包含在建立从客户机工作站到所有合适的数据库服务器的通信时所需的信息。
数据库(database)目录包含客户机所连接到的所有数据库的数据库访问信息。
DB2 Design Advisor 是获得有效的分区建议的最直接的工具,可以通过 Control Center GUI 或 db2advis 命令行工具来使用它。通过一个可更新的分区映射,结合一个散列算法,可以指定分区键与数据库分区的映射,这个映射可用于确定每个数据行的位置和检索。
于是,对于大型的表,工作负载可以分布在多个分区上,而更小的表也可以存储在一个或多个数据库分区上。由于每个数据库分区都有它的数据上的本地索引,因此提高了本地数据访问的性能。
DB2 还支持部分分块(de-clustering),在此情况下,表和表空间可以分布在可用分区的一个子集上。取决于数据库分区的数量,您可以有一个或多个单分区的数据库分区组,以及一个或多个多分区的数据库分区组。每个分区必须使用一个惟一的分区号,而同一个数据库分区可以属于一个或多个数据库分区组中。
为了确保包含系统编目表的分区能够快速恢复,应避免将用户表也放在那个数据库分区上。为此,可以将用户表放在不包括 IBMCATGROUP 数据库分区组中的数据库分区的数据库分区组中。
除非想要利用与更大的表的并置,否则应该将小型的表放在单分区的数据库分区组中。应避免使中等规模的表横跨太多的数据库分区。例如,对于一个 100 MB 的表,将它放在包含 16 个分区的数据库分区组上可能比将它放在包含 32 个分区的数据库分区组上得到的性能要好。
您可以使用数据库分区组来将在线事务处理(OLTP)表与决策支持(DSS)表隔离开来,以确保 OLTP 事务的性能不受负面影响。
在多分区数据库分区组中,如果索引是分区键的超集,那么只能创建一个惟一的索引。
在创建数据库时,应确保在用于数据库位置的 "ON" 子句中指定一个本地(非共享)目录。例如,
CREATE DATABASE SAMPLE ON /db2_db
其中 /db2_db is 是一个预先存在的本地目录。
在默认情况下,数据库管理器配置中的默认数据库路径(DBTDBPATH)参数是 instance owner(被 NFS 共享)的 home 目录的位置。如果在不指定数据库位置的情况下创建数据库,那么将使用 DBTDBPATH 创建数据库,这里 DBTDBPATH 指向共享的 instance-owner 目录。这样将降低性能。
创建数据库之后,应该确保每个数据分区还有它自己的日志本地目录。您可以使用以下命令:
db2_all ";db2 update db cfg for SAMPLE using NEWLOGPATH /db2_db/logs"
节点号被自动附加在路径的后面。这样做是为了维护多逻辑节点配置中路径的惟一性。
本文讲解了在 DB2 UDB 中使用 Data Partitioning Feature (DPF) 的理论基础,详细解释了 DPF 的安装过程和一些重要概念,并且谈到在 SUSE Linux Enterprise 环境中启用 DPF 时在设计上的一些考虑。更好地理解了 SUSE Linux 环境中的 DB2 DPF 之后,就可以很快地掌握如何在 SUSE Linux 环境中启用 DPF。
原文链接:http://www-128.ibm.com/developerworks/cn/db2/library/techarticles/dm-0601poon/index.html
