利用实时统计功能实现 DB2 数据库智能化管理
2010-03-31 00:00:00 来源:WEB开发网DB2 实时统计功能的背景介绍
DB2 Z/OS 被广泛应用于海量数据存储领域,例如大型银行,连锁超市,政府部门等。TB 级的用户数据存储在成千上万的用户表中。一般来说,一个 ERP 应用大约有 5 万个用户表和索引。用户表中的数据时时刻刻都发生着变化,这就要求数据库管理员定期地对 DB2 系统中的表和索引进行维护,例如,定期做数据备份 (COPY) 以防数据丢失 , 重组数据表空间 (REORG) 获得更访问和存储效率 , 更新表和索引的统计信息 (RUNSTATS) 保证给查询优化器能提供更准确的路径选择依据。
在传统的工作模式下,数据库管理员 (DBA) 在非交易时间(例如,银行、超市等关门以后到第二天重新营业这一段时间窗口)定期对所有数据进行维护。这种数据维护方式并不对数据表空间或索引空间加以分析区分。而随着用户数据量的日益增长,对数据的日常维护变得越来越难以控制。面对成千上万的表和索引,短暂的数据维护时间窗口难以满足需求。同时,数据量的增长也意味着数据库管理员工作量的增加,企业的用人成本也随之提高。
有经验的数据库管理员常常会有这样的想法:假如有一个 DB2 用户表,在上一次备份之后至今的一段时间里,只有很少甚至根本就没有任何数据写操作(INSERT, DELETE, UPDATE), 那不就不需要在下一个数据维护时间窗口对他进行备份操作了吗?那么怎样才能找出那些真正需要做数据维护的表呢?理论上,只有那些在上一次备份之后发生了较多数据更新的表空间,才有必要再次做备份。然而,数据库管理员并不知道哪些表空间发生了较多的数据更新。DB2 实时统计功能正是为了解决这一问题而设计的。
如图 1 所示,实时统计管理器 (RTS Manager) 通过监控所有表和索引的变化,获得表和索引的实时信息并且记录在实时统计表(RTS Tables)中。DB2 同时提供了用户应用程序与实时统计表的接口——存储过程 DSNACCOR。用户可以通过调用 DSNACCOR 设定对象选择标准,准确地找到那些需要做 COPY, REORG, RUNSTATS 的对象,从而减小在数据维护中资源的浪费。
图 1. DB2 实时统计工作原理
查看原图(大图)
如何启用 DB2 实时统计功能
对于 DB2 z/os V8 和 V9, RTS 的启用方式有所不同。下面分别介绍如何在 V8 和 V9 中设置和启用 RTS。
在 DB2 V8 中,需要通过以下步骤手工启用实时统计功能:
1. 创建 RTS 用于记录统计信息的所需数据库对象:数据库 , 表空间 , 表和索引(如表 1 中所示)。DB2 安装包中提供了创建这些对象的 DDL。
2. 设置 DB2 系统更新 RTS 表的周期值。在 DB2 的系统参数(ZPARM)中 , STATSINT 表示每隔多长时间,RTS 管理器将内存中的统计信息写到位于磁盘的 RTS 表当中去。例如,STATSINT=30 表示每隔 30 秒更新一次 RTS 表。可见,RTS 表里保存的内容实际上是准实时的统计信息。更新周期设置得越短,RTS 表就越接近实时状态,但同时 RTS 对整个系统造成的负载(CPU, I/O 开销)也越大。
3. 手工启动 RTS 数据库 : -START DB(DSNRTSDB)。创建好了 RTS 数据库,DB2 首先将其设置成 STOP 状态。只有当用户手工 START 这个数据库以后,RTS 数据库才处于读写状态,这时 RTS 管理器就可以将收集并保存在内存中的实时统计信息写到 RTS 表中去了。
4. 为 RTS 表中的对象设置初始值。在创建并且已经启动了 RTS database 以后,DB2 会自动地为系统中每一个已经存在的对象(表空间和索引空间),往 RTS 表里面插入对应的一行用于记录该对象的统计信息,如果是分区的表空间和索引空间,则会为每一个分区往 RTS 表插入一行记录。但这时的刚插入的记录里面的信息还没有初始化,RTS 还无法通过监控变化值来更新相应列的值。用户需要通过执行一些 UTILITY( 如:REORG, COPY, LOAD, RUNSTATS … ) 来初始化 RTS 表中不同的列。例如,表 SYSIBM.TABLESPACESTATS 有一个列:TOTALROWS,表示在一个表空间或者表空间的分区中有多少条记录。刚开始这个列的值是 NULL,只有通过对这个表空间或者表空间的分区执行 REORG 或者 LOAD utility 以后,DB2 才能得到它的初始值。在这个初始值的基础上,RTS 管理器通过监视对这个对象的 INSERT, DELETE 次数来得到实时的 TOTALROWS 值。
表 1. DB2 V8 的 RTS 对象
RTS 数据库对象 | 对象说明 |
DSNRTSDB | RTS 数据库名称 |
DSNRTSTS | RTS 表空间名称 |
SYSIBM.TABLESPACESTATS | 记录关于表空间统计信息的 RTS 表名称 |
SYSIBM.INDEXSPACESTATS | 记录关于索引空间统计信息的 RTS 表名称 |
SYSIBM.TABLESPACESTATS_IX | Unique index on SYSIBM.TABLESPACESTATS (DBID, PSID, PARTITION) |
SYSIBM.INDEXSPACESTATS_IX | Unique index on SYSIBM.INDEXSPACESTATS (DBID, ISOBID, and PARTITION) |
考虑到 RTS 越来越受 DB2 V8 用户的欢迎,为了简化 RTS 的启用流程,DB2 V9 以后,RTS 表成了 DB2 系统表(Catalog)的一部分。表 2 是 DB2 V9 RTS 对象的说明,注意和 V8 时相比,对象名字有所变化。而 RTS 的启用也不再像 V8 一样复杂了。
表 2. DB2 V9 的 RTS 对象
RTS 数据库对象 | 对象说明 |
DSNDB06 | Catalog 的数据名称(RTS 表是 Catalog 的一部分)。 |
SYSRTSTS | RTS 表空间名称 |
SYSIBM. SYSTABLESPACESTATS | 记录关于表空间统计信息的 RTS 表名称 |
SYSIBM. SYSINDEXSPACESTATS | 记录关于索引空间统计信息的 RTS 表名称 |
SYSIBM.DSNRTX01 | Unique index on SYSIBM.TABLESPACESTATS (DBID,PSID,PARTITION,INSTANCE) |
SYSIBM. DSNRTX02 | Unique index on SYSIBM.INDEXSPACESTATS (DBID,ISOBID,PARTITION,INSTANCE) |
SYSIBM. DSNRTX03 | Index on SYSIBM.INDEXSPACESTATS (CREATOR,NAME) |
因此,DB2 V9 用户不再需要手工创建 RTS 对象。RTS 的对象会在 V9 的安装或者升级的过程中创建。DB2 V9 用户也不再需要手工启动 RTS 数据库。如果用户是新安装的 DB2 V9,那么只需要为 RTS 表对象设置初始值;如果是从 V8 升级到 V9, 并且 RTS 表已经在 V8 时已经做过初始化,那就不需要做任何事,RTS 已经平滑地从 V8 过渡到 V9。
RTS 表的具体说明
要了解 RTS 管理器究竟收集哪些信息,以及怎样利用这些信息来帮助用户管理和维护 DB2 数据库系统,最好的方法就是看一下 RTS 表中各个列的含义。表 3 和表 4 分别列出了 SYSIBM.SYSTABLESPACESTATS 和 SYSIBM.SYSINDEXSTATS 中主要列的详细说明,并且按照不同 UTILITY 的相关性对所有列进行了分类。
表 3. SYSIBM.SYSTABLESPACESTATS 记录表空间实时统计信息
列名字 | 说明 |
表空间 /分区基本信息 | |
DBNAME | 数据库名称 |
NAME | 表空间名称 |
PARTITION | 分区号(非分区表该值 =0) |
UPDATESTATSTIME | 最后一次更新这条记录的时间 |
表空间 /分区大小相关信息 | |
NACTIVE | 已经格式化的物理页数 |
NPAGES | 用于存放实际数据的页数(NACTIVE 中除去已经格式化但还未使用的物理页) |
EXTENTS | 该表空间 / 分区对应的物理文件已分配的扩展数 |
SPACE | 该表空间 / 分区对应的物理文件已分配的比特数(KB) |
TOTALROWS | 该表空间 / 分区总共的记录数 |
与数据压缩率有关的信息 | |
DATASIZE | 所有的记录(压缩后)大小总和 |
UNCOMPRESSED- DATASIZE | 如果没有压缩,所有的记录(压缩后)大小总和 |
与 REORG utility相关的信息 | |
REORGLASTTIME | 对该表空间 / 分区最后一次执行 REORG 的时间 |
LOADLASTTIME | 对该表空间 / 分区最后一次执行 LOAD REPLACE 的时间 |
REORGINSERTS | 自从上一次执行 REORG 或 LOAD REPLACE 之后,插入到该表空间 / 分区的记录数 |
REORGDELETES | 自从上一次执行 REORG 或 LOAD REPLACE 之后,从该表空间 / 分区删除的记录数 |
REORGUPDATES | 自从上一次执行 REORG 或 LOAD REPLACE 之后,该表空间 / 分区被更改的记录数 |
REORGDISORGLOB | 自从上一次执行 REORG 或 LOAD REPLACE 之后,没有紧凑插入到该表空间 / 分区的记录数。(当插入一条记录时,按照 cluster index 定义会得到一个最理想的页号,如果实际插入的页号距离理想页号在 16 个物理页之内,就认为这次插入是紧凑插入)。 |
REORGUNCLUSTINS | 自从上一次执行 REORG 或 LOAD REPLACE 之后,没有紧凑插入到该 LOB 表空间 / 分区的 LOB 数。(当插入一条 LOB 时,如果该 LOB 占用的 chunk 数最少,就认为这次 LOB 插入是紧凑插入) |
REORGMASSDELETE | 自从上一次执行 REORG 或 LOAD REPLACE 之后,该表空间 / 分区发生 MASS DELETE 的次数 |
REORGNEARINDREF | 自从上一次执行 REORG 或 LOAD REPLACE 之后,该表空间 / 分区发生记录溢出并且溢出的记录所在页距离原来记录所在页较近(16 个物理页以内)的次数。 |
REORGFARINDREF | 自从上一次执行 REORG 或 LOAD REPLACE 之后,该表空间 / 分区发生记录溢出并且溢出的记录所在页距离原来记录所在页较远(16 个物理页以外)的次数。 |
与 COPY utility相关的信息 | |
COPYLASTTIME | 对该表空间 / 分区最后一次执行 COPY utility 的时间 |
COPYUPDATEDPAGES | 自从上一次执行 COPY 之后 , 该表空间 / 分区被更改过的不同的页数 |
COPYCHANGES | 自从上一次执行 COPY 之后 , 该表空间 / 分区发生的 INSERT, DELETE, UPDATE 的次数 |
COPYUPDATELRSN | 自从上一次执行 COPY 之后 , 该表空间 / 分区发生的第一次更改的 LRSN 或者 RBA |
COPYUPDATETIME | 自从上一次执行 COPY 之后 , 该表空间 / 分区发生的第一次更改的时间值 |
与 RUNSTATS utility相关的信息 | |
STATSLASTTIME | 对该表空间 / 分区最后一次执行 RUNSTATS utility 的时间 |
STATSINSERTS | 自从上一次执行 RUNSTATS 之后 , 插入到该表空间 / 分区的记录数 |
STATSDELETES | 自从上一次执行 RUNSTATS 之后 , 从该表空间 / 分区删除的记录数 |
STATSUPDATES | 自从上一次执行 RUNSTATS 之后 , 该表空间 / 分区更改的记录数 |
STATSMASSDELETE | 自从上一次执行 RUNSTATS 之后,该表空间 / 分区发生 MASS DELETE 的次数 |
表 4. SYSIBM. SYSINDEXSTATS 记录索引空间实时统计信息
列名字 | 说明 |
索引空间 /分区基本信息 | |
DBNAME | 数据库名称 |
INDEXSPACE | 索引空间名称 |
PARTITION | 分区号(非分区索引该值 =0) |
CREATOR | 创建者名称 |
NAME | 索引名称 |
UPDATESTATSTIME | 最后一次更新这条记录的时间 |
LASTUSED | 该索引 / 分区最后一次被使用的日期 |
索引空间 /分区大小相关信息 | |
NLEVELS | 该索引树的层次数 |
NPAGES | 用于存放实际数据的页数(NACTIVE 中除去已经已经格式化但还未使用的物理页) |
NLEAF | 该索引 / 分区中 LEAF 页的数目 |
NACTIVE | 已经格式化的物理页数 |
SPACE | 该索引空间 / 分区对应的物理文件已分配的比特数(KB) |
EXTENTS | 该表空间 / 分区对应的物理文件已分配的扩展数 |
TOTALENTRIES | 该索引 / 分区中的词条数目 |
与 REORG,REBUILD utility相关的信息 | |
LOADLASTTIME | 对该索引空间 / 分区最后一次执行 LOAD REPLACE 的时间 |
REBUILDLASTTIME | 对该索引空间 / 分区最后一次执行 REBUILD 的时间 |
REORGLASTTIME | 对该索引空间 / 分区最后一次执行 REORG 的时间 |
REORGINSERTS | 自从上一次执行 REORG,REBUILD INDEX 或 LOAD REPLACE 之后,插入到该索引空间 / 分区的词条数 |
REORGDELETES | 自从上一次执行 REORG,REBUILD INDEX 或 LOAD REPLACE 之后,从该索引空间 / 分区删除的词条数 |
REORGAPPENDINSERT | 自从上一次执行 REORG,REBUILD INDEX 或 LOAD REPLACE 之后,插入到该索引空间 / 分区并且 KEY 值大于当时最大 KEY 值的词条数 |
REORGPSEUDODELETES | 自从上一次执行 REORG,REBUILD INDEX 或 LOAD REPLACE 之后,从该索引空间 / 分区被标示删除的词条数。 |
REORGMASSDELETE | 自从上一次执行 REORG,REBUILD INDEX 或 LOAD REPLACE 之后,发生 MASS DELETE 的次数。 |
REORGLEAFNEAR | 自从上一次执行 REORG,REBUILD INDEX 或 LOAD REPLACE 之后,发生 LEAF 页分裂并且新生成的 LEAF 页距离原来的 LEAF 页较近(16 个物理页以内)的次数。 |
REORGLEAFFAR | 自从上一次执行 REORG,REBUILD INDEX 或 LOAD REPLACE 之后,发生 LEAF 页分裂并且新生成的 LEAF 页距离原来的 LEAF 页较远(16 个物理页以外)的次数。 |
REORGNUMLEVELS | 自从上一次执行 REORG,REBUILD INDEX 或 LOAD REPLACE 之后,新增加的索引树的层次数。 |
与 COPY utility相关的信息 | |
COPYLASTTIME | 该索引空间 / 分区最后一次执行 COPY utility 的时间 |
COPYUPDATEDPAGES | 自从上一次执行 COPY 之后 , 该索引空间 / 分区被更改过的不同的页数 |
COPYCHANGES | 自从上一次执行 COPY 之后 , 该索引空间 / 分区发生的 INSERT, DELETE, UPDATE 的次数 |
COPYUPDATELRSN | 自从上一次执行 COPY 之后 , 该索引空间 / 分区发生的第一次更改的 LRSN 或者 RBA |
COPYUPDATETIME | 自从上一次执行 COPY 之后 , 该索引空间 / 分区发生的第一次更改的时间值 |
与 RUNSTATS utility相关的信息 | |
STATSLASTTIME | 该索引空间 / 分区最后一次执行 RUNSTATS utility 的时间 |
STATSINSERTS | 自从上一次执行 RUNSTATS 之后 , 插入到该索引空间 / 分区的词条数 |
STATSDELETES | 自从上一次执行 RUNSTATS 之后 , 从该索引空间 / 分区删除的词条数 |
STATSMASSDELETE | 自从上一次执行 RUNSTATS 之后,该索引空间 / 分区发生 MASS DELETE 的次数 |
RTS 管理器如何维护 RTS 表
RTS 管理器在 DB2 中表现为一个系统的进程。这个进程会为每一个 DB2 对象(也就是 RTS 表中的每一行)在内存中建立一个模块。RTS 管理器实时地监控着 DB2 系统的所有操作,并且把相关的统计信息更新到内存模块中。每隔一段时间(周期为 STATSINT), RTS 管理器会将内存中的所有对象的统计信息写到磁盘的 RTS 表中。另外,执行某些特殊的 UTILITY( 如 REORG, LOAD, REBUILD 等 ) 或者 STOP 某个表 / 索引空间时,RTS 管理器也会把相应对象的统计信息写到 RTS 表中。
在 DATA SHARING 环境下,每个 DB2 成员都有自己的 RTS 管理器,不同 DB2 成员维护自己统计信息;由表 3 和表 4 可见,大部分 RTS 信息都类似于一些计数器,所以当每个 DB2 成员往 RTS 表写入信息时,实际上就是将自己统计的这部分信息累加到计数器上。图 2 所示的是在 DATA SHARING 情况下,各个 DB2 成员的 RTS 管理器共同维护 RTS 表的情况。
图 2. DATA SHARING 环境下 RTS 管理器共同维护 RTS 表
那么,究竟哪些操作需要被 RTS 管理器统计并收集起来呢?其实,表 3 和表 4 对 RTS 表各个列的解释就已经告诉了我们答案。例如,某个表空间或者索引空间使用的物理页数变多,或者新增加了一个扩展,或者索引树的层次变大等等,都会导致 RTS 管理器更新那些和空间大小相关的列;再如,在某个表空间插入了一条记录,SYSIBM.SYSTABLESPACESTATS 表中相关计数器(TOTALROWS,REORGINSERTS, COPYCHANGES, STATSINSERTS)都需要相应的加 1。总之,除了读操作以外,对 DB2 对象的任何操作都会被统计到 RTS 表对应的计数器中。
同样,通过表 3 和表 4 的解释我们也不难知道,REORG, LOAD, COPY, RUNSTATS, REBUILD INDEX 等 UTILITY 会去更改 RTS 表中最后一次执行这些 UTILITY 的时间,同时还要把与之相关的计数器清零。可以说,每次执行这些 UTILITY,实际上就结束了 RTS 管理器对某个数据库对象的一个监视周期;同时也为下一个监视周期设定了初始值,开始了对该对象的新一轮的监视。
如何利用存储过程 DSNACCOR 访问 RTS 表。
RTS 表就像其他的 DB2 表一样,可以通过 SQL 语句进行查询。那为什么我们还需要通过存储过程 DSNACCOR 来访问呢?这是因为 DSNACCOR 这个存储过程定义了非常方便的用户接口,并且在其内部定义了通用的对象选择原则;用户只需要告诉这个存储过程自己希望选择什么样的对象进行维护,DSNACCOR 就会自动地返回用户想要的结果。图 3 显示了 DSNACCOR 的调用接口。
图 3. DSNACCOR 调用接口
这里,我们不再一一列举各个输入参数的意义。我们将通过几个调用 DSNACCOR 的例子来展示如何选择我们所需的对象。
清单 1. 选择需要执行 full image COPY 的表空间
CALLING DSNACCOR STORPROC FOR:
QUERY TYPE : 'COPY'
OBJECT TYPE : TS
ICTYPE : F
CRITERIA
: DBNAME='MYDB'
CRUPDATEDPAGESPCT : 20
CRCHANGESPCT : 10
CRDAYSNCLASTCOPY : 3
在清单 1 中,用户希望选出满足以下条件的表空间来执行 FULL IMAGE COPY 操作:
所在数据库名是 MYDB;
自从上一次执行 COPY 以后,有 20% 以上的物理页被更新过 , 或者;
自从上一次执行 COPY 以后,有 10% 以上的记录被更新过 , 或者;
自从上一次执行 COPY 是 3 天以前。
清单 2. 选择需要执行 REORG 的表空间
CALLING DSNACCOR STORPROC FOR:
QUERY TYPE : 'REORG'
OBJECT TYPE : TS
RRTInsDelUpdPct : 20
RRTUnclustInsPct : 5
RRTMassDelLimit : 3
RRTIndRefLimit : 5
在清单 2 中,用户希望选出满足以下条件的表空间来执行 REORG 操作:
自从上一次执行 REORG 以后,有 20% 以上的记录被更新过 (INSERT, DELETE, UPDATE), 或者;
自从上一次执行 REORG 以后,有 5% 以上的记录是非紧凑插入的,或者;
自从上一次执行 REORG 以后,有 3 次以上的 MASS DELETE, 或者;
自从上一次执行 REORG 以后,有 5% 以上的记录有溢出。
清单 3. 选择需要执行 RUNSTATS 的索引空间
CALLING DSNACCOR STORPROC FOR:
QUERY TYPE : 'RUNSTATS'
OBJECT TYPE : IX
CHKLVL : 16
SRIInsDelPct : 10
SRIInsDelAbs : 500
清单 3 是要选出自从上一次执行 RUNSTATS 以后,有 10% 以上并且总数超过 500 的词条被更新过的索引空间。
DSNACCOR 会根据客户的输入参数,对 RTS 表中的数据进行计算,把满足条件的表空间或者索引空间名字放入结果集返回给用户。通过以上这些例子可见,数据库管理员只需要在每次数据维护之前,通过告诉 DSNACCOR 自己定义的数据维护选择标准,就能得到所需的维护对象。
可见,有了实时统计信息以后,数据库管理员可以又方便又准确地选择需要维护的 DB2 对象,这样既节约了宝贵的数据维护时间窗口,又节省了系统的资源,同时也节省了企业的人力维护成本。
更多精彩
赞助商链接