DB2数据库初始调优和设计方面的考虑


  本文标签:DB2数据库 初始调优 设计

  导读:对于一个应用程序的性能来说,其中数据库的性能是一个重要因素  。由于应用程序及其相关的数据总会随着时间的推移而发生变化,因此必须不断地对数据库进行调优从而使其保持最佳水准  。然而,花在调优上的努力应该在一个合理的范围之内  。调优应该有一个度,超过了这个度的一切努力只能产生负面影响  。如果应用程序的性能还不能令人满意,那么就应该考虑其他的变通办法,比如将该应用程序移到更快的平台上  。下文就以讲解DB2数据库初始调优设计方面为例为大家讲解数据库的调优  。

  本文中提到的命令和语法是基于 DB2 UDB V7 的,如果您使用的是 DB2 UDB V8,可能会稍有差异  。

  数据库设计方面的考虑

  数据库调优始于设计阶段  。假设硬件的选择是基于其他方面的考虑的,那么第一个要决定的就是存储架构  。DB2 所使用的驱动器越多、越快,则潜在的性能将越好  。对于表空间(tablespaces )和其他对象(日志,备份文件,等等)的位置应该小心仔细地加以规划  。尤其重要的是,要尽量保证日志和备份处在不同的驱动器上,这样做不但是为了性能,也是为了便于恢复  。

  表空间设计是整个数据库设计中的一个重要部分  。通过创建不止一个的用户表空间可以增强性能  。在下面三种情况下,使用多个表空间就很有用:

  控制 I/O,如果这些表空间可以位于不同的驱动器上的话  。
使用不同的页面大小(pagesize)  。
控制缓冲池  。
在大多数情况下,隔离的表空间是为索引和大型对象而创建的  。以相同的页面大小创建多于一个的表空间并没有什么好处  。

  比起系统管理的表空间来,数据库管理(Database-managed)的表空间(尤其是在原始设备上)能够提供更好的性能  。在决定页面大小时要记住,DB2 在一页上最多只能放 255 行,剩余的空间将不被使用  。例如,如果平均行长度是 50 字节,那么一页最多使用的空间是 50*255=12750 字节  。如果将该表放在页面大小为 16K 或者 32K 的表空间中,那么有些页就会被浪费  。反之,如果有些表有更长的行,或者有很多的列,(具体的限制参见 SQL 参考手册中 CREATE TABLE 语句),那么页面大小就需要大于 4K  。如果要以一种连续的方式(例如,群集表)来访问数据,那么采用更大的页面大小可以获得更好的性能,相反,如果对数据的访问采用的是随机方式,那么最好使用尽可能小的页面大小  。

  每个表空间都与具有相同页面大小的一个缓冲池相关联(一个缓冲池可以与不止一个的表空间相关联)  。在使用多个缓冲池的时候要谨慎  。由于可用的存储是有限的,为某个缓冲池分配过多的空间势必减少其他缓冲池的宽度,从而导致整体性能的降低  。缓冲池调优最好是在检测数据库性能和基准的基础上进行  。DB2 善于动态地管理可用空间,因此,在大多数情况下使用最少数量的缓冲池可以得到较好的性能  。

  长期以来,表设计的重要性就在于标准化  。无冗余数据占据着最少的空间,并且具有最好的完整性  。然而,无冗余数据并不能提供最好的性能  。为了消除一点点的冗余,需要创建额外的表,这使得查询时需要额外地结合这额外创建的表,从而增加查询的复杂性  。在平衡这两方面的需求时,需要有正确的判断  。通常,通过生成冗余数据可以增加性能,但是这要采取一种受约束的方式,即冗余数据所采取的形式必须是索引和汇总表  。如果要经常访问汇总数据,那么后者可以明显增加性能  。对刷新频率的评估应该以信息需要保持的新鲜程度为依据  。

  索引是性能调优中最重要的方面之一  。通常,对表的访问都是基于一些标准的  。根据组成这些标准的一些列构建索引,可以动态地减少查询相关的开销  。对于在线维护的不稳定的表应该创建少量的索引(一个或两个),而对于大型的历史性的表,由于需要通过多种方式进行查询,则需要创建很多的索引  。一条索引中的列数应该尽量地少,除非很多查询都可以通过一个“index only”搜索来完成  。为了这个目的, INCLUDE 选项允许将其他字段附加到索引上,其开销则小于完全索引方式  。可以选择一个表的某一索引作为群集索引,或者在 REORGANIZE 命令中指定该索引  。表数据将保持由该索引指定的顺序  。当大量的查询基于该索引访问大量的行时,这种做法很有用  。索引通常被放在它们自己的表空间中,拥有它们自己的缓冲池,以防止数据页数量很多时会将索引页挤出  。

  应用程序设计方面的考虑

  应用程序设计同样会影响到数据库  。首要的一步就是要确保应用程序只要求数据库管理器做必需的工作  。例如,通过使用 SELECT * 来请求所有的列在一定程度上可以使得程序的速度加快,但是这样做却降低了性能,因为需要额外的数据移动,而且阻止了“index only”扫描  。在查询中包括不必要的子句,例如 ORDER BY 或者 DISTINCT ,就是请求数据库管理器做额外工作的一个例子  。如果列的顺序对应用程序的运行没有影响,那么就可以省下排序所花的时间  。

  控制锁(locking)特性对于增加数据库的吞吐量非常重要  。即使是对于只读事务,提交也具有极大的重要性,因为对于这样的事务同样也要使用锁  。选择正确的隔离级别非常重要  。应该使用尽可能低的隔离级别,只要在这种级别上应用程序能够运行就行了  。对于锁来说,使用可重复读隔离级别是极其昂贵的,并且也减少了并发性  。只要不打算对结果集进行更新,那么就应该包括 FOR READ ONLY 子句  。这样就可以保证独占的锁不被获得  。 FOR UPDATE 子句将消除对重新获得更高级别锁的需求  。在某些环境下,在查询之前通过应用程序获得一个表锁可以防止获取很多的行锁,从而防止了对锁的逐步升级  。

  查询优化是另一个可以节省大量资源的方面  。优化的级别可以通过数据库配置参数 dft_queryopt 进行设置  。并且,在静态 SQL 中可以通过 PREP 和 BIND 命令进行重设,在动态 SQL 中可以通过 SET CURRENT QUERY OPTIMIZATION 语句进行重设  。对于复杂的查询,可能需要第 5 级或者更高的级别  。可以使用 db2batch 工具来评测花在编译和执行 SQL 语句上的时间  。至于结果,要记住,静态 SQL 语句通常是编译一次,执行多次;对于动态 SQL 也是一样,因为结果要缓存  。

  初始调优

  在创建了数据库和表空间之后,可以使用 Performance Wizard 来设置初始数据库配置  。选择数据库以及“Configure Performance Using Wizard”选项  。这将允许更快地装载数据  。在创建了数据对象之后,就应该装载数据  。

  调优的第一步就是使用 RUNSTATS 命令收集统计信息  。为了获得整套的统计信息,应该指定“WITH DISTRIBUTION AND INDEXES ALL”选项  。 RUNSTATS 应该是数据库维护的一个常规的部分  。应该根据数据库的更新率有规律地(每日,每周,每月)调用 RUNSTATS   。如果对数据作了大的更改(装载或者删除了大量的行),也应运行 RUNSTATS 命令  。统计信息可用于决定对于一个查询来说哪一个访问计划是最有效的  。在执行了 RUNSTATS 命令之后,受到影响的包应该重新绑定  。

  在此之后应该再次执行 Performance Wizard,这一次是为了指定要填充的数据库  。Performance Wizard 将更改某些数据库配置参数  。如果正确地解决了这些问题,那么由 Performance Wizard 产生的值通常会比较理想  。Performance Wizard 使您可以在第一屏恢复先前的配置(如果有的话)  。您应该认真阅读窗口中的解说  。最后一屏将显示老的和新的数据库配置,并对所有的更改用粗体进行高亮显示  。

  如果在测试时性能不令人满意,那么就应该使用 Database System Monitor(参见 System Monitor Guide and Reference以了解细节),或者将问题的源头缩小至几个事务,来查探这一问题的起因  。对于特定的查询,解释工具(参见 Administration Guide 以了解细节)提供了有关性能问题可能的起因的有价值的信息  。根据这些信息,可以对索引结构或者数据库参数作出更改  。

  结束语

  先前的讨论强调了调优时需要考虑的的一些主要方面  。调优是一个反复的过程  。随着时间的推移,数据库中的数据以及应用程序需要更改  。这时,为了适应新的需要,应该对性能进行检测并对数据库作出更改  。对数据库的配置参数或者其他方面所做的更改要有基准,要打破常规  。在某些时候,有些更改看上去是对的,实际上却会对数据库产生负面的影响  。希望大家通过上文的学习,都能够很好的掌握关于DB2数据库初始调优和设计方面的知识  。