baoshengfei
作者baoshengfei·2016-01-30 21:58
软件架构设计师·EM

简谈DB2的性能调优

字数 2909阅读 2841评论 1赞 1

       以前在实验室工作的时候,总觉得DB2的优化是一个很难的话题。不仅是因为涉及存储、CPU、内存、系统参数、实例参数、数据库参数等各种数据库管理知识,更重要的是因为DB2里面分成了很多组件,每个组建都有几十甚至几百个参数或者监控项。做一个通用的优化方法几乎就是不可能的。

       现在,作为数据库的使用者,看到生产系统上各种各样的性能问题。就不能因为方法难而不去做了。解决了一些问题以后,发现对终端客户来说,一些通用的方法还是有必要的。因为这些方法差不多能解决80%以上的性能问题。

       反正也睡不着,总结一下这些年优化DB2性能的经验吧。

       在我经历的这些问题的性能优化中,90%的性能问题发生在应用程序,而这90%的问题又基本上通过以下办法中的前两个解决80%以上的问题。

  • 保持准确的统计信息

      统计信息时合理的执行计划的基础,没有准确的统计信息,就不一定能生成最优的执行计划。举个例子,一张表T中实际优1000万行数据,现在有根据某一列近似唯一键的索引去精确查询一条记录。如果统计信息准确,那执行计划就会选择这条索引去查询;但是如果如果统计信息很长时间没有更新了,而上一次更新统计信息的时候,表里面只有4条数据,那执行计划可能就是一个全表扫描了。

      那怎样看统计信息相关的信息呢?其实,和统计信息相关的系统表有好几个。因为是简单总结,我只用syscat.tables做个例子。用以下语句可以看到这张表上一次更新统计信息的时间和上次更新统计信息时,这张表中数据的行数:

      db2 "select substr(tabname,1,50), stats_time, card from siesta.tables where tabname='<tabname>' with ur"

     更新统计信息的方法也有很多讲究,这里,我们简单粗暴的使用:

      db2 "runstats on table <tabschema>.<tabname> with distribution and detailed indexes all table sample system(<per>)"

  • 建立合适的索引

       虽然标题很简单,但是建立合适的索引却不是一件能简单做到的事情。简单来讲,有五条规则:        

       1. 在能过滤出最少数据集的过滤条件列上创建的索引

       2. 在关键的连接条件列上建立的索引。

       3. 再排序、聚合的列上考虑使用索引。

       4. 注意使用index only scan。

       5. 设计能使用索引的数据模型和写能使用索引的语句。

        例如,应用经常使用身份证号查询某个客户,而身份证号几乎能精确的定位到一个客户,那身份证号就是一个很好的索引列。

        再例如,某一行的一列表示状态,所有的数据中,只有4种状态0,1,2,3。而状态是0的数据占特别少数,而我们的查询确经常查询状态是0的数据,那么,状态也是一个很好的索引列选项。

        还有一种使用索引以后,性能提升很明显的案例,就是select count(*)这种语句,因为如果我们把这个语句中涉及的列全都加到索引中,这种语句可以使用index only scan。

        最后简单说一下有一些语句,例如substr(c1,1,20), func(c1,c2)这种用法,不太容易选择索引,即使选择了索引,效率也不一定高。

  • 写简单的语句

        简单的语句更容易生成好的执行计划,遇到问题的时候也更容易诊断。简单不是说语句短,而是说可读性要好。曾经见到过一个语句,是5张表进行关联,where条件中类似于下面的写法:

        where (a.c1=b.c1) or (a.c1=c.c1) or (a.c1=d.c1) or (a.c1=e.c1)

        实际的语句条件比这复杂很多,后来我们改成了Union的形式以后,效率提高了很多。

  • 交易系统给用户返回尽量少的数据集

        返回尽量少的数据有两个方法,一个是在查询中增加查询条件或选用过滤性强的条件,一个是使用fetch first n rows only的方式查出来前几行。

        其实,对于交易系统来说,本来是不需要给前台返回太多数据的。例如,一个客户关系系统,即使查询中给客户经理返回2000条数据,他怎样从这里面找到需要的数据呢?

  • 使用正确的rebind方式并且和合适的条件下对程序包进行rebind

        为什么要rebind呢?因为静态语句的执行计划在bind的时候就已经保存在数据库中了。随着业务数据的不断变化,静态语句的执行计划并不会因为这些数据的变化(即使进行了runstats)而重新优化。

        为了让静态语句的执行计划更合理,应该选择好的时间进行runstats,并且进行rebind。

        有些存储过程和静态语句使用的目的是为了封装业务逻辑,编译的开销对系统整体运行并没有太大的压力,或者说如果编译的时间和执行的时间比较起来非常短,其实可以对这些package使用reopt always的方式进行绑定,以保证每次执行都生成当前统计信息下的最优的执行计划。

  • 使用正确的数据迁移方式

      我们的好多系统批处理的时候会涉及数据迁移。交易系统中,如果时间可以接受,采用insert into ......select的方式没有问题。但是理论上,最快的数据迁移方式是load......from cursor。

如果觉得我的文章对您有用,请点赞。您的支持将鼓励我继续创作!

1

添加新评论1 条评论

huangdkhuangdk数据库架构师IBM
2016-02-01 11:18
三板斧先上,runstats,reorg,rebind  :)
Ctrl+Enter 发表

作者其他文章

相关文章

相关问题

相关资料

X社区推广