简介
IDS 的基本体系结构包括三个主要组件:数据存储器、内存结构和后台处理器或虚拟处理器。本文将详细地讨论每一个组件,并提供一些关于如何主动监控数据库引擎的性能,以及如何更为积极主动地进行调优的实用技巧。 确切地说,本文将详细地讨论下列主题:
数据存储器及调优指南
内存结构及调优指南
后台处理器及调优指南
数据存储器及调优指南
磁盘是 IDS 的基本数据存储设备。IDS 可以使用两种类型的磁盘设备:成熟的(cooked)磁盘设备和原始的(raw)磁盘设备。成熟的磁盘设备指的是安装到操作系统的磁盘区域,其中包含了常规文件和文件系统。成熟的磁盘设备对用户来说是可视的。在 Unix 系统中,您可以使用命令 df -k 来显示系统上的所有成熟磁盘设备。例如:
sys3508:omcadmin > df -k
Filesystem kbytes used avail capacity Mounted on
/dev/md/dsk/d0 1094523 669404 370393 65% /
/dev/md/dsk/d8 7560147 5601614 1882932 75% /usr
/proc 0 0 0 0% /proc
fd 0 0 0 0% /dev/fd
mnttab 0 0 0 0% /etc/mnttab
/dev/md/dsk/d36 2285263 1440973 798585 65% /var
swap 1025776 8 1025768 1% /var/run
swap 1060400 34632 1025768 4% /tmp
/dev/md/dsk/d16 10912273 6242461 4560690 58% /usr/gsm/ne_data
/dev/md/dsk/d12 3009327 1121085 1828056 39% /usr/gsm/logs
以上输出指出了系统上所有的成熟磁盘设备。Filesystem 列显示了所有成熟磁盘设备,而 Mounted on 列显示了相应设备上安装的所有文件系统。例如,设备 /dev/md/dsk/d0 安装在 / 或根文件系统上,/dev/md/dsk/d36 安装在 /var 文件系统上,/dev/md/dsk/d16 安装在 /usr/gsm/ne_data 文件系统上等。Kbytes 列展示了该设备所占的磁盘总空间,used 展示了该设备当前已使用的磁盘空间,而 avail 列则展示了该设备可用的剩余磁盘空间。另一方面,原始磁盘设备指的是无法安装到操作系统的磁盘片,对用户来说是不可视的。Informix 建议尽可能地使用原始磁盘设备,因为原始磁盘设备不用安装到操作系统上,并可以将数据服务器内存中的数据直接传送到磁盘上,而无需先将之复制到操作系统的内存池中,这比成熟的磁盘设备要快得多。此外,原始设备比成熟设备安全,因为对用户而言,它们是不可视的(除了 root 用户)。使用文件系统作为数据存储设备有一个潜在的危险,当文件系统由于某些操作系统的错误而崩溃,且有一个数据库事务正在进行时,数据库服务器将认为数据库事务已经成功完成,但实际上,该事务正陷入操作系统缓冲区中;这最终将导致数据库中的某些不一致。关于如何为 IDS 分配成熟和原始磁盘设备的详细过程,请参阅 IBM Informix Dynamic Server Administrator's Guide,Version 9.4(本文后面将称作 Administrator's Guide)。
Informix Dynamic Server 在 dbspace 中存储其数据。dbspace 是 Informix 的数据存储单元,它包含一个或多个块(chunk),更确切地说是由一个或多个块来支持。块(chunk)在术语上是指磁盘上的连续空间。在 IDS 9.40 之前的 IDS 版本中,对于块的最大长度具有一个硬限制;一个块不能超过 2 G。从 IDS 9.40 开始,如果在大块(large chunk)模式下配置 IDS,则取消这一限制。这是一项革命性的提高;通过这项提高,IDS 可以更有效地利用磁盘空间,并更容易地管理它们。IDS 使用 onspaces 实用程序来配置和管理 dbspaces。以下是 onspaces 实用程序的用法:
$ onspaces --
Usage:
onspaces { -a spacename -p path -o offset -s size [-m path offset]
{ { [-Mo mdoffset] [-Ms mdsize] } | -U }
} |
{ -c { -d DBspace [-t]
-p path -o offset -s size [-m path offset] } |
{ -b BLOBspace -g pagesize
-p path -o offset -s size [-m path offset] } |
{ -S SBLOBspace [-t]
-p path -o offset -s size [-m path offset]
[-Mo mdoffset] [-Ms mdsize] [-Df default-list] } |
{ -x Extspace -l Location } } |
{ -d spacename [-p path -o offset] [-f] [-y] } |
{ -f[y] off [DBspace-list] | on [DBspace-list] } |
{ -m spacename {-p path -o offset -m path offset [-y] |
-f filename} } |
{ -r spacename [-y] } |
{ -s spacename -p path -o offset {-O | -D} [-y] } |
{ -ch sbspacename -Df default-list } |
{ -cl sbspacename }
-a - Add a chunk to a DBspace, BLOBspace or SBLOBspace
-c - Create a DBspace, BLOBspace, SBLOBspace or Extspace
-d - Drop a DBspace, BLOBspace, SBLOBspace, Extspace, or chunk
-f - Change dataskip default for specified DBspaces
-m - Add mirroring to an existing DBspace, BLOBspace or SBLOBspace
-r - Turn mirroring off for a DBspace, BLOBspace or SBLOBspace
-s - Change the status of a chunk
-ch - Change default list for smart large object space
-cl - garbage collect smart large objects that are not referenced
default-list = {[LOGGING = {ON|OFF}] [,ACCESSTIME = {ON|OFF}]
[,AVG_LO_SIZE = {1 - 2097152}] }
只有用户 Informix 或具有 DBA 权限的用户可以使用此实用程序。
那么,我们该如何配置 dbspaces 呢?没有一套硬性规则;适当的配置应基于您系统上的可用磁盘。但是为了最优化整体性能,Informix 为我们提供了一些指南,其中最为关键的就是为不同的数据配置不同的 dbspace。我们可以将 IDS 数据分成下列几类:
逻辑日志数据;由逻辑日志生成的数据;
物理日志数据;由物理日志生成的数据;
表数据;数据库表中的数据;
索引数据;由表上的索引生成的数据;
二进制对象数据,如大型文本和内部图形;
临时数据;通过对表进行排序、更改和创建索引而生成的数据。
首次初始化 IDS 时,它会将其所有的数据、逻辑日志数据、物理日志数据和其他临时数据放置在根 dbspace 中。为了获得高性能,我们需要创建不同的 dbspaces,并且将逻辑日志数据和物理日志数据从 rootdbspace 移出。将索引数据从表数据中分离出来也是有益的。在为临时数据创建临时 dbspace 之后,Informix 还建议将 DBSPACETEMP 配置参数设置为您系统上所配置的多个临时 dbspace 的名称,这将减少磁盘 I/O,如果将 PDQPRIORITY 设置为大于 0 的值,这将提高创建临时表的速度,并允许并行排序或插入。
另一重要指南就是在磁盘中分散 dbspace。这当然要受到硬件拓扑的限制,但其思想就是将关键的 dbspace(例如根 dbspace、逻辑日志 dbspace 和物理日志 dbspace)放置在更快的磁盘上,因为那些 dbspace 将进行大多数的磁盘 I/O 活动,并且也会将磁盘 I/O 负载均衡地分散在磁盘中。创建了合适的 dbspace 之后,我们需要不断地监控那些 dbspace 上的磁盘 I/O 活动,识别是否存在过热点(hot spot),并且在必要时对其进行调优,以获取更好的性能。
Dbsapce I/O 是通过磁盘读写来衡量的。如果某些 dbspace 具有较多的磁盘读写,而其他磁盘却较为空闲,那么该系统可能存在磁盘 I/O 瓶颈。较为平衡的 dbspace I/O 将缓解系统磁盘 I/O 负载,从而提高系统的整体性能。下列脚本将显示当前每个 dbspace 的 I/O 统计信息:
select d.name, fname[15,25] path_name, sum(pagesread) diskreads,
sum(pageswritten) diskwrites
from syschkio c, syschunks k, sysdbspaces d
where d.dbsnum = k.dbsnum
and k.chknum = c.chknum
group by 1, 2
order by 1
其输出结果如下:
name path_name diskreads diskwrites
airgen_10_0 uild95/ltmp 3672 7964
airgen_main_dbs uild95/ltmp 13545 32903
llog uild95/ltmp 19 51633
rootdbs uild95/ltmp 211 43117
temp1 uild95/ltmp 3015 3122
temp2 uild95/ltmp 3218 3317
您可以通过查询 sysmaster 数据库中的 sysptprof 表,进一步确定哪些表具有多数磁盘读写:
select dbsname, tabname, (isreads + pagreads) diskreads, (iswrites + pagwrites)
diskwrites
from sysptprof
order by 3 desc, 4 desc
其输出如下所示:
dbsname tabname diskreads diskwrites
airgen_10_0 fanout_param 84567 3094
airgen_main_dbs sysindices 78381 0
airgen_10_0 ne_nmo_i 75819 5
airgen_10_0 ne_nmo 75440 297
airgen_main_dbs ne_main 62610 28322
airgen_10_0 systables 37342 466
airgen_10_0 syscolumns 34539 4609
airgen_10_0 457_484 32838 42
airgen_10_0 453_480 30009 1
airgen_main_dbs syscolumns 29531 4550
airgen_10_5 syscolumns 28824 4552
airgen_10_0 456_483 25448 14
airgen_10_0 458_485 23278 177
airgen_main_dbs 452_483 22412 31
基于该查询所获得的输出,您可以发现 airgen_cm_db 数据库中的 ne_main 表具有最多磁盘 I/O,如果当前 dbspace 所承受的磁盘 I/O 过于繁重,那么可以考虑将该表移到另一 dbspace 中。
内存结构及调优指南
内存结构是 IDS 体系结构中最为复杂的组件。因为 IDS 使用的内存部分被数据库服务器线程以及其他用户和虚拟进程共享,因此该部分内存通常被称作共享内存。由于参与进程(在本例中是虚拟处理机)不需要维护共享内存中的私有数据副本,共享内存可以使数据库服务器减少总的内存使用。共享内存还能减少磁盘 I/O,这是因为作为公共池来管理的缓冲区,是在数据库服务器级基础上而不是在每进程基础上被刷新的。而且,因为这些数据已经作为前面读取操作的结果存在于共享内存中了,所以虚拟进程通常可以避免从磁盘读取数据。磁盘 I/O 的减少也减少了执行时间。共享内存提供了最快地进行进程间通信的方法,因为它以内存转换的速度来处理读写消息。
在初始化 IDS 时,它就创建了共享内存,其中包括以下 4 个区(portion):
常驻区(resident portion);
虚拟区(virtual portion);
IPC 通信或消息区(IPC communications or message portion);
虚拟扩展区(virtual-extension portion)。
现在,让我们仔细地看看每一部分,并查看其内容以及它们分别是如何工作的。
常驻部分存储数据库服务器运行时大小固定的数据结构,它具有下列几个部分:
共享内存头
缓冲池
逻辑日志缓冲区
物理日志缓冲区
锁表
共享内存头包含共享内存中所有其他结构的描述,包括内部表和缓冲池。它还包含到这些结构位置的指针。当一个虚拟进程首次附加到共享内存中时,它读取共享内存头中的地址信息,获取指向其他所有结构的方向。共享内存头是在初始化 IDS 时创建的,并且不能进行调优。缓冲池存储 IDS 从 dbspace 所读取的数据,更确切地说是数据库对象数据,例如表数据和索引数据,或者是从磁盘所读取的存储过程。然后,ESQL 或其他客户程序将操作该数据。
缓冲池占用了常驻区中最大的部分。所有的缓冲区将被组织到一个较长的最近最少使用(least-recently-used,LRU)缓冲区队列中,并通过最近最少使用(LRU)机制进行管理。缓冲区的获取是通过使用锁存器(latch)和锁访问信息来管理的,该锁存器称作 mutex。逻辑日志缓冲区是用来存储最后一次备份开始的逻辑日志记录的。
逻辑日志记录保存了 SQL 语句对数据库数据进行的修改。在初始化 IDS 时,它创建三个逻辑日志缓冲区。那些逻辑日志缓冲区以循环方式起作用,以确保将获得的每一条逻辑日志记录都被刷新到磁盘中。物理日志缓冲区被用来保存缓冲池中已修改数据库记录的前映像(before-image)。在 IDS 删除或修改一条数据库记录之前,它将捕获这一原始记录的快照并存储其原始值,以防事务失败。这就称作前映像(before-image),被用于恢复数据,确保了数据库的完整性。在初始化 IDS 时,它创建了两个物理日志缓冲区,而它们与逻辑日志缓冲区一样,以循环方式运作。锁表是一个包含可用锁的池;每个用户会话都需要一定数量的锁来连接数据库服务器并执行数据库操作,例如 select、insert、delete 和 update。
除了共享内存头之外,所有这些部分都是可以控制并用 Informix 配置参数进行调优的。下表列举了与 IDS 共享内存的常驻区有关的所有配置参数: