理想的索引
通过检查一个应用程序中的SQL语句,你可以建立一个假想的完美的索引。
首先,索引所包括的所有列都是WHERE子句,这使得索引的审查可以用于将不合格的行拒于结果集之外。将这些列放在索引的开始。当在SQL语句上执行EXPLAIN时,这会使得MATCHCOLS的价值最大化。其次,确保索引以适当的顺序含有这些列(依照ORDER BY子句),从而可以避免进行排序。这可以在执行EXPLAIN时,通过检查PLAN_TABLE的所有不同的SORT*列来验证。
最后,如果可能的话,将所有的列包含在索引的SELECT中,这样就不需要访问表中的行了。索引条目可以提供所有的请求数据。这将在EXPLAIN中以INDEXONLY = Y的方式表现出来。
在很多情况下,实现如此理想的索引的代价太大了,或者说是不切合实际的,甚至是不可能实现的,因为所涉及的列的数量太大了。组成一个索引的列的数目在体系结构方面有限制,并且对于一个索引条目的总长也有限制(尽管这些限制实际上允许相当大的索引条目尺寸和灵活性)。此外,这也是出于索引维护成本的考虑。建立理想的索引可使查询性能获得较高提升,但是对于SQL写入DB2数据库(INSERT、UPDATE或DELETE)就有消极的影响。因此,你应该经常选择实现只包含WHERE和ORDER BY语句中涉及的列的索引。
并行处理的考虑事项
几年来,通过实现了并行处理的各种方法,DB2在数据访问方面的性能获得了改进。为了改进数据密集型只读查询的性能,DB2 V3引进了查询I/O并行机制。在这种类型的并行性中, DB2充分利用了可用的I/O带宽,并使分区表空间中成为可能。利用这种方法,DB2使得一个查询中的多个并发I/O请求可同时进行,并在多个数据分区中执行了并行的I/O处理。这代表性地使得I/O绑定查询所耗费时间的显著降低,同时出现了CPU时间的较小增长。
DB2 V4引入了另外的并行性技术,称为查询CP并行性。该方法将并行处理扩展至处理密集型的查询。用该方法,单个查询可使DB2生成数个任务,并行执行数据访问。对于这种类型的并行性,分区表空间显示出非常好的的性能提升。
DB2 UDB V5通过引进综合系统查询并行性,更进一步地扩展了并行处理。当查询CP并行性在DB2子系统中为某个查询使用了多个任务时,该方法使得DB2数据共享群中的所有成员能够处理一个单一的查询。主要为只读形式的I/O密集型和处理密集型查询可以从这种类型的并行性中获益。
并行访问的授权
在DB2环境下使系统获得并行性能力有一定的难度。首先,在DB2子系统级别,并行访问由安装面板DSNTIP4控制。DSNTIP4上的MAX DEGREE 选项决定并行性的最大程度(并行任务的最大数目)。默认值为0,意味着对于DB2可调用的并行性程度没有上限。我建议你估计虚拟存储容量,以及你的z/OS环境限制,还应根据需要调该参数,因此DB2将不会创建超过你的虚拟存储容量可以应对的并行任务。
通过BIND PLAN和BIND PACKAGE命令的DEGREE选项,你能够控制DB2是否使用并行处理。设定DEGREE(1)阻止并行处理,而DEGREE(ANY)允许并行处理。为了获得进一步的灵活性,动态SQL允许在一个计划或包内更改该选项,通过SET CURRENT DEGREE语句即可实现,SET CURRENT DEGREE语句用于控制某个寄存器中的数值。
当一个计划或包与DEGREE(ANY)绑定,或者CURRENT DEGREE寄存器设定为ANY时,DB2优化器考虑并行性是否是可能的,从而获得最有效的最终计划。如果并行性是不可能的,那么将会选择下一个允许并行性的最有效的最终计划。
限制分区扫描
限制分区扫描是允许DB2在分区表空间中限制数据扫描的一种方法。根据SQL谓词的值,DB2能够决定最低和最高的分区,这可能包含了被SQL语句所请求的表的行,之后便将数据扫描限制在分区的范围内。为了使用该技术,SQL必须提供一个在分区索引的第一个关键列上的谓词。
并行性建议
为了使并行处理的性能卓越化,需要考虑以下事项:
尽可能均匀地对表空间进行分区,因为并行性程度会受到数据不均匀的影响。DB2通常在最大物理分区的基础上将表空间划分为逻辑片段。为DB2的应用程序处理分配尽可能多的中央处理器(CP),以及尽可能多的I/O设备和通道。对于I/O密集型查询,确保分区的数量与可以访问表空间的I/O通道数量相同。对于处理密集型查询,确保分区的数量与用于跨共享数据群处理查询的CP数量相同。
将表空间和索引的分区放在单独的DASD卷上,并且(如果可能的话)独立控制这些单元以便使I/O冲突最小化。
在规则的基础上执行RUNSTATS实用工具集,以便获得分区级别的统计表。
监视虚拟缓冲池的阈值和使用情况,确信你提供了足够的缓冲池空间来使调用的并行性程度最大化。
缓冲池的考虑事项
缓冲池的重要性
大多数专家认为在DB2环境下,数据库缓冲池是影响性能的最关键的因素。很多DB2的体系结构和设计是基于尽可能多的或实际上避免物理I/O这一概念。
DB2缓冲池由临近存储器的插槽组成。从DASD读入之后,数据和索引页进入这些插槽并且呆在其中,直到DB2缓冲管理器决定这些插槽需要被其他数据占用。被应用程序请求的数据通常存储在存储器内,而不是在外部的DASD,这种情形越经常出现,整体的性能就越好。本质上,数据是被重新利用了,从而使得应用程序需要的I/O数量最小化。
释放缓冲池插槽的决定基于最近最少使用(LRU)法则。DB2维护着两个LRU列表,一个是关于随机访问页的,另一个是关于顺序访问页的。这便阻止了完全占用缓冲池的大表扫描,以及对随机操作的负面影响。通过各种阈值的使用,DB2为你提供了改进缓冲池性能的额外灵活性。关于这些阈值的进一步详细讨论见DB2 SQL参考手册的2.7.4部分。
缓冲池的合适大小
缓冲池尺寸的指定取决于可用的存储量(包括中央部分和扩展部分)。我建议你分析一下缓冲池分配,并且增加它的尺寸直到再也没有由于增加的分配而产生的额外吞吐量,或是MVS分页速率到达不可接受的程度。这将通过逐渐增加的VPSIZE来实现,只要DASD I/Os的数目保持减少,在分页的成本超过减少I/O的收益之前,VPSIZE将持续增加。
在早期,GETPAGES的数量可能是DB2工作量的最好衡量标准。缓冲池的用途是为了使I/O最小化(异步读取通常意味着一次做一个,这是基于性能立场上的一般要求。另一方面,同步读取通常意味着从DASD的随机I/O,因为所请求的页在缓冲池内找不到)。统计报告显示le 每一个缓冲池中的GETPAGES和同步读取的数量。一个被普遍接受的ROT说,如果同步读取的GETPAGES比率小于10:1,那么你应该考虑配置更大缓冲池了。
多缓冲池配置
如果你的操作环境允许为DB2缓存配置容量相当大的存储器,那么多缓冲池配置可以最大限度地为特定的应用程序或数据库提供改善的性能。然而,请注意由于采用多个缓冲池,监视它们的工作效率变得更加重要。普遍来讲,对配置多缓冲池有如下建议:
将表空间和它们相联系的索引分离到不同的池,以便使索引I/O最小化。将具有不同数据访问模式的数据分别置于不同的缓冲池中。典型地,批处理和查询应用程序含有大量的连续处理,而OLTP的数据访问在本质上往往比较随机。这就提供了一种方法,来开发不同的阈值以在一个缓冲池适应各种特定类型的数据访问。
为了隔离应用程序,提供一个单独的缓冲池。这就提供了一种方法,来严密监视一个存在运行问题的应用程序,或是测试新的应用程序。如果分类性能在你的环境下很重要,那么就为共作文件创建一个独立的缓冲池。对于相对比较小但是更新很快的表,足够大的独立缓冲池可以同时消除读取和书写I/Os。为只读表(小的、参考表)设立单独的缓冲池也可以提高性能。
总结
经过深思熟虑的数据库设计可以提供重大的性能优势,但是它必须在应用程序的开发过程中尽早开始。上述很多原则,在DB2的早期就已经被明智的开发人员所利用,并且至今仍保持着它们的正确性。然而清楚DB2功能上的进步,以及影响你当前和以后应用程序的其他领域内的硬件和软件技术的变化,同样也是至关紧要的。当数据库性能成为发展过程的一个重要焦点时,你的数据库设计,将使你更有可能为你的DB2应用程序提供最优化的性能。