大型机上运行的程序作为历史悠久,应用领域广泛的商业应用程序,一直是用户关注的焦点。大型机应用程序的性能问题会导致程序消耗更多的系统资源,这就意味着大型机系统需要为运行这个程序提供更多的 CPU 时间。根据测算,大型机上的 CPU 每运行一分钟平均的开销大约是 15 USD,由此可见针对应用程序的性能调优可以帮助用户提高程序效率,减少程序消耗的 CPU 时间,推迟由于系统资源不足导致的软硬件升级计划,有效的降低大型机的运行成本。目前很多大型金融机构的应用程序开发中心成立了专门的部门对应用程序进行性能调优。而 DB2 for z/OS 作为大型机上绝大多数应用程序最主要的数据库平台,针对 DB2 for z/OS 应用程序的性能调优就成了每个用户关注的要点。
应用程序的性能问题最直接的表现为两点:
1. | CPU 时间过长 |
2. | WAIT 时间过长 |
这两点也恰恰是分析性能问题的出发点 ( 见图 1) 。
如果性能问题表现为 CPU 时间长,应该从应用程序代码和 DB2 执行的 SQL 两方面分析;如果性能问题表现为 WAIT 时间长,则应该从 I/O 和 Service Task 两方面分析,进而逐步细化问题产生的原因,进而最终定位性能问题根源。
工欲善其事,必先利其器。想要快速准确地发现、分析并解决问题,使用相应工具辅助是一种常见的手段。针对大型机应用程序性能分析,业界常用的工具有两类: 针对应用程序的分析工具和针对 DB2 的分析工具 ( 见图 2 和 表 1),它们相辅相成,结合使用可以达到事半功倍的效果。
名称 | 特点 | |
---|---|---|
1. 针对应用程序的分析工具 | STROBE | STROBE 和 APA 是同一类型的工具,它们记录了目标应用程序在访问数据库、操作系统、文件系统一系列动作中与此应用程序相关的性能开销 |
APA | ||
2. 针对 DB2 的分析工具 | DB2 PM | OMEGAMON 可以看作是 DB2 PM 的升级版,它记录了 DB2 中所有的应用的性能开销 |
OMEGAMON XE for DB2 |
STROBE 通过浏览器界面发现并展示性能问题,从导致性能问题的 2 个基本点 CPU 和 WAIT 出发,快速定位性能问题(见图 3),本文在应用性能分析实例中采用 STROBE 报表作为样例。
DB2 PM 以文本的方式展示性能信息,详细记录 DB2 中的各种性能开销,为分析 DB2 相关的性能问题提供了最详尽的分析报告 ( 见图 4)。
可能有人会问:这些辅助分析工具是必需的吗?不用任何工具就不能分析大型机系统的问题吗?答案是:理论上这些辅助工具不是必需的,所有信息都可以在大型机提供的各种系统数据中找到(见表 2)。但是,就像交通工具(汽车,飞机等)可以方便人们的生活一样,使用性能分析工具也可以极大地提高性能分析工作的效率。
名称 | 作用 | |
---|---|---|
1 | SMF records | 基于 SMF records 可以产生各种 Trace,包括分析 DB2 的 Trace, 用于分析各种性能,负载方面的问题。 |
2 | LOGREC data | 基于 LOGREC data 可以产生 EREP Report,用于分析硬件及系统方面的问题,包括 I/O Device , Process failure 等。 |
3 | SYSLOG data | 记录了 Console 上的信息和操作员使用的命令 |
4 | DUMP | 产生一个 Sequential 的 DUMP File,记录了系统内存中的信息。 |
其实上述性能分析工具就是对这些系统提供的信息进行包装和再加工,以一种更友好的方式提供给用户。如 STROBE 和 OMEGAMON XE for DB2 等工具,它们都是通 Instrumentation Facility Interface (IFI) 来获取 DB2 相关的性能信息,而这些信息也会被记录到 SMF records 中。
DB2 for z/OS 应用程序性能分析的基本流程 ( 见表 3)
1. 定位问题类型 | 应用程序代码性能问题 | DB2 SQL 性能问题 | I/O 性能问题 |
2. 分析问题原因 | 重复调用同一条语句 | 使用 Table Scan 访问方法 | Getpage 数量太大 |
未能正常使用 CURSOR | Where 语句使用了 Stage 2 的 Predicate | Buffer Pool 不够大 | |
3. 提出改进意见 | 根据问题特点提出改进意见 |
下面就使用 3 个实例来展示如何分析 表 3 中列出的典型问题
步骤 1:定位问题
通过性能分析报告 ( 见图 5) 可以发现 Module 0800 中的一段代码 (Line 484 到 Line 514) 在不停地’打开’ (OPEN) 和’关闭’ (CLOSE) 一个文件,16.95 %的 CPU 时间都用于执行此段代码。
步骤 2:分析问题 -结合应用程序代码
结合 Module 0800 的代码发现这是由于 OPEN/CLOSE 文件的子程序被一个外层循环所不停的调用导致重复调用同一条语句。
步骤 3: 改进意见
把 OPEN/CLOSE 两条语句放在子程序循环体以外,这样调用子程序时只需要 OPEN/CLOSE 一次就可以。
步骤 1:定位问题
通过性能分析报告( 见图 6 )可以发现,单单一条 SELECT 语句 (SQL 530) 消就耗了 12.03% CPU 和 40.07% WAIT。
步骤 2:分析问题 - 参考 DB2 Explain 和 DB2 Catalog Statistics
分析 SQL 语句的性能开销就要知道这些消耗是发生在哪些 SQL 相关的元素上 ( 见 图 7)。一条 SQL 语句的 CPU 开销通常由 4 种元素开销构成 ( 见表 4),而 I/O 的发生则是因为要取回的记录不在内存中,需要到磁盘上取。DB2 最终计算 SQL 相关的每一项元素开销的基础数据是来源于 DB2 CATALOG STATISTICS, 通常对 SQL 性能分析是从 ACCESS PATH 开始的,也就是从分析 SQL 的 EXPLAIN OUTPUT 开始。
CPU | 开销类型 | SQL元素 | 说明 |
---|---|---|---|
1. | Base Cost | TABLE 属性 | 如果 TABLE 是压缩的,在读取数据时会因为解压缩而产生 CPU 开销 |
2. | Page Cost | INDEX/DATA PAGES | INDEX 过滤出来的结果集越小,需要访问的 INDEX 以及 DATA PAGES 就越少,这方面的 CPU 开销就越少 |
3. | Scan Cost | INDEX 设计 /SORT | 如果组成 INDEX 的 COLUMNS 每一个都有很好的过滤性,这个 INDEX 需要 SCAN 的 record 数量就会比较少,这方面的 CPU 开销就少;SORT 会 SCAN 结果集并排序,会消耗大量 CPU |
4. | Row Cost | WHERE 子句 | Where 子句的过滤性越强,最终返回结果集就越少,CPU 开销就越小 |
图 6 中 SQL 530 这条 SELECT 性能不好,通常从分析它怎么访问 DB2 开始,也就是要分析这条 SQL 语句的 ACCESS PATH。相关的信息都在 DB2 的 EXPLAIN OUTPUT 中。查看 SQL 530 的 EXPLAIN OUTPUT( 见图 8), 可以发现此条 SQL 使用了 INDEX SCAN 的方式从 DB2 中取回数据 (ACCESS TYPE : I),使用的 INDEX 是 IINMBP(ACCESSNAME)。
通过表 4 可以判断导致 SQL 530 性能不好的元素是 INDEX IINMBP。由于 DB2 计算 INDEX 相关开销是基于 CATALOG STATISTICS,所以接下来需要查看 CATALOG STATISTICS 中 INDEX 相关信息 ( 见图 9)。
从图 9 中可以发现,SQL 530 选用的 INDEX IINMBP 的第一个 COLUMN(INST_NO) 的 COLCARD 是 1,也就是说在这个 COLUMN 上,只有一种值,所以这个 COLUMN 没有任何过滤性。这正是 SQL 530 使用 INDEX SCAN 性能仍然不好的原因。
步骤 3: 改进意见
从图 9 中可以看到,INDEX IINMBP 的第二个 COLUMN(ACCT_NO) 的 COLCARD 是 23350108,这和 Table 的 CARDF 是一样的,也就是说这个 Table 中,ACCT_NO 每个 RECORD 都有不同的值,具有非常好的过滤性。因此改进建议是使用 ALTER 语句改变 INDEX IINMBP 中 COLUMN 的顺序为 IINMBP(ACCT_NO, INST_NO) 。
步骤 1:定位问题
通过性能分析报告 ( 见图 10) 可以发现,SQL 1700( 见清单 1) 消耗了 74.99% CPU 和 11.54 的 I/O, 伴随着 SQL 1700 有超过 395000 次的 GET PAGE 请求,并且导致了 110376 条记录被 INSERT 到 WORKFILE 中,最终返回 7001 条结果。
SELECT SYSIBM.SYSTABLES.NAME FROM SYSIBM.SYSTABLES WHERE ( ( ( SYSIBM.SYSTABLES.NAME IN (SELECT SYSIBM.SYSCOLUMNS.TBNAME FROM SYSIBM.SYSCOLUMNS WHERE SYSIBM.SYSCOLUMNS.TBCREATOR > ‘ ‘ AND TBCREATOR < ‘ Z ’ ) ) ) ) AND SYSIBM.SYSTABLES.TYPE <> ‘ A ’ ORDER BY SYSIBM.SYSTABLES.NAME |
步骤 2:分析问题 - 结合 SQL 语义
通过表 4 可以判断导致 SQL 1700 性能不好的元素是 WHERE 子句,WHERE 子句中的 SUB-SELECT 会产生子结果集,这个子结果集再和外层的 WHERE 条件一一匹配,这样就产生了一个很大的最终结果集,而这些结果记录不在内存中,就导致了很多的 GET PAGE 请求。结合 SQL 语义后发现,其实这个 SUB-SELECT 是不必要的,可以转化成同样意义的两个 WHERE 条件,这样就不会有子结果集的产生,和额外的 GET PAGE 请求。
步骤 3: 改进意见
改写 SQL( 见清单 2)
SELECT NAME FROM SYSIBM.SYSTABLES WHERE CREATOR > ‘ ‘ AND CREATOR < ‘ Z ’ AND TYPE <> ‘ A ’ ORDER BY NAME |
再次运行 SQL 1700,通过性能报告 ( 见图 11) 可以发现,改进后 SQL 只消耗了 3.35% CPU,并且只有 7001 条记录被插入 WORKFILE 中,没有额外的 GET PAGE 请求。
学习
获得产品和技术
联系客服