(转)https://mp.weixin.qq.com/s?__biz=MjM5NTk0MTM1Mw==&mid=2650629396&idx=1&sn=3ec17927b3d32c7bc9692c809d1f69cb&chksm=bef91b92898e928417a7608b2ef56deef78b184c65e5fef118dbe8708d4a2d1ebd717979e7f2&mpshare=1&scene=1&srcid=08212GNx1FDgPZQOXMQKKF3l#rd
为了帮助大家更好地进行DB2的性能优化,社区组织社区专家针对一些共性问题及难点分享经验。以下内容来自活动“Db2数据库性能优化经验交流”,主要由以下社区专家及会员分享:leilin、topzgm、岳彩波、beyondmch、yellow-fin等
提醒:文章末尾有彩蛋,如果你是Db2达人,可不要错过~
01
如何发现性能问题?通过什么定位?
1、收集信息。
2、分析
3、找到问题点解决
第一步 操作系统级别性能
CPU监控:
ps -elf | sort +5 -rn | more 第6列代表CPU使用的计数器
I/O使用率:
iostat -D 收集磁盘I/O信息
内存占用率:
讨论的内存指的是虚拟内存(virtual memory),包括物理内存(physical memory)与交换空间(swap space)
vmstat -> avm 当前系统中已经激活的虚拟内存页的数量(该数值不包含文件系统缓存)
vmstat -> fre 系统中平均空闲页的数量(不能完全代表系统中可用的空闲内存:文件系统缓存驻留内存,并不会返还给空闲列表,除非被虚拟内存管理器盗取)
svmon -> clnt与in use交叉项 代表有多少内存被文件系统使用(加上free项,可以初步认为是该系统中可以被应用程序所使用的内存)
第二步 数据库级别性能
1. db2grep -dump | more 查看服务器安装了几个DB2版本
2. ps -elf | grep db2inst1 查看数据库进程的CPU计数器
3. db2 get dbm cfg | grep -i dft_mon 确认快照打开
4. 实例级快照,了解当前实例有多少应用程序在执行
db2 get snapshot for database manager -> Remote connections & Local connections
5. 数据库级快照
连接数信息:applications connected currently,appls executing in db manager currently
锁信息:锁总数,锁等待数量,锁等待总时间,当前数据库锁列表占用内存,死锁次数,锁升级次数,锁超时次数
排序信息:
排序是CPU杀手,过多的排序会造成CPU的极大消耗;
排序溢出是说,如果排序堆无法容纳排序数据,就会被溢出到临时空间;
排序是一种状态,根源在SQL语句;
数据索引I/O信息:
逻辑读 DB2向缓冲池请求的次数 逻辑读越多,需要的物理I/O就越少
物理读 如果请求的数据页不在缓冲池,需要从磁盘中读取数据页的次数
吞吐量或事务信息:
提交/回滚事务数,执行动态和静态语句次数,增删改查次数
( rows read / rows selected ) 是一个非常重要的性能指标,它表示为了检索一行数据需要读取多少行,该值越大,表示代价越高,需要的I/O越多,可调优的余地越大
事务日志信息:日志I/O在很大程度上会影响数据库整体的性能
6. 应用程序快照
在数据库快照中发现存在大量的逻辑读,通过应用程序快照可以细化到某条特定的语句
7. 表空间快照
在数据库快照中发现存在大量的逻辑读,通过表空间快照可以轻松地定位哪个表空间被频繁使用
8. 表快照
如果发现一个表的页数很少,但是读的行数非常多,那么可以合理地猜测该表在某些查询语句中可能处于NLJOIN的内部子节点
9. 动态SQL快照:SQL执行次数,总共读的行数,消耗的CPU,逻辑物理读数量,排序数量等
第三步 内存使用监控
1. db2pd -osinfo
系统内存使用情况
2. db2pd -dbptnmem
整个实例的内存使用情况
3. db2pd -memsets
内存段使用情况
在实例中会有多个不同的内存段,每一个内存段中可能有一个或者多个内存池
ipcs -a | grep 578814120 内存段映射到操作系统共享内存IPC段
FMP与trace内存段很少造成性能问题
4. db2pd -mempool
深入内存池信息
5. db2pd -db <dbname> -memsets / -mempool
数据库级别内存段和内存池信息
02
优化过程中的优先级问题?
在Db2优化过程中,我已知的有如下手段
1.索引
2.sql语句优化(分析执行语句后重写sql)
3.runstats信息收集
请问优化过程中,入手的优先级顺序是什么呢,还有其他手段吗?
这“三板斧”已经可以解决很多问题了,DB2的优化手段很多,如果想深入了解,上传几个文件供参考。
附件:
(以下附件在如下地址可下载:http://www.talkwithtrend.com/Question/403149)
DB2BP_System_Performance_0813.pdf
DB2BP_Query_Tuning_0508I.pdf
DB2BP_Storage_1009I.pdf
DB2BP_Physical_Design_OLTP_0412.pdf
DB2BP_Physical_Design_0508I.pdf
03
如何监控到db2某个时段内发生的sql?以及sql的响应时间和资源消耗情况?
这是个共性问题,实现这个目标的DB2工具也比较多,例如:
1)SNAPSHOT管理视图,示例脚本如下:
db2 "select SNAPSHOT_TIMESTAMP,NUM_EXECUTIONS,TOTAL_EXEC_TIME,STMT_TEXT from sysibmadm.snapdyn_sql with ur" | more
以上快照结果存储在数据库中,读取和分析方便。
2)db2top工具,示例脚本如下:
a)db2top -d xdb -f test1.txt -C -m 5 -i 30
每隔30秒取得快照一次,时间段为5分钟
b)db2top -d xdb -f test1.txt -b D
分析刚才取得的快照数据
以上快照结果存储在文件中,读取和分析可能不太方便,但是收集的信息宽度更大。
04
临时表的创建和维护?
在做复杂业务分析时,一个存储过程也会用到很多临时表(存储业务分析某一步的中间结果),这些表的数据经常变化(每个周期都会被清空再装入),还需要和别的表做关联,那么这种表在建表的时候有什么要注意的吗?为了提升程序性能,优化时考虑这些表吗?要建立索引吗?runstats应该保持在什么状态?需要reorg吗?
分享一:
这些临时表不是会话表(DGTT 或 CGTT)吧?如果每次调用存储过程生成的临时表数据变化都比较大,建议在存储过程中搜集统计信息(调用sysproc.admin_cmd('runstats on table <临时表>'),因为临时表每次调用一般都清空,没有必要reorg;建不建索引,具体看表关联的需要,存储过程一般是加工数据的,临时表一般不需要建索引。另外,建议将存储过程对应的package绑定成 REOPT ALWAYS的,这样每次调用该存储过程都会根据最新的统计信息生成新的执行计划,通常也会提高性能。
分享二:
根据个人实践经验,分享如下2点:
1)如果是DGTT(DECLARE GLOBAL TEMPORARY TABLE)/CGTT(CREATE GLOBAL TEMPORARY TABLE),则一般不必对其建立index,也不需对其进行runstats、reorg,因为DB2查询优化器在每次分析和执行SQL时,都会对包含DGTT/CGTT的SQL进行重新优化并且生成新的最优access plan。
2)如果不是DGTT/CGTT,而是自己create table x1的普通表,即使这些普通表经常变化,只要建立index、runstats、reorg带来的收益远远大于建立index、runstats、reorg耗费的成本,就应该建立index、runstats、reorg,否则不必。复杂业务分析的存储过程,更加需要遵从这个“收益与成本原则”。例如,一个复杂分析,不建立index/runstats/reorg时查询需要5分钟时间;但是如果建立index/runstats/reorg需要耗时3秒种时间,而此时查询提高到只需10秒时间;这样的3秒种的成本,带来了查询时间减少4分50秒的收益,这样的成本与收益是有利的。
05
怎么查什么数据占用了系统临时表空间呢?
Db2 在排序、表关联等处理时会用到系统临时表空间,顺序是Sortheap不足时溢出到临时表空间对应的bufferpool,buffpool再不足时溢出到磁盘。如果想看数据是否使用了系统临时表空间、使用了多少,直接db2 list tablespaces show detail 看看系统临时表空间的Used pages即可, 或者db2top 进去看表空间(按 t ),再看系统临时表空间上是否有Writes。
06
有个表空间一直都在增长,但是查数据库正在执行哪些sql又没查到东西,请问是不是load的原因呢?
分享一:
如果没有SQL在运行,可以用db2 list utilities 或 db2pd -util 看看是否有load在执行,并找到load表的表空间或其索引表空间,对应看一下。
分享二:
一点思路,仅供参考:
使用db2top -d xdb1,然后切换到工具的Table页,看看这个表空间下哪些/那个表在一直读写。如果表空间在增长,但是在db2top中看不到该表空间下任何表在读写,再从load方面入手,适用db2 list utilities来看看有何进展。
07
lob存储优化的问题?
请教个问题
我们有一个表很大,500G,lob大对象没有采用内联方式,现在要想让它的大小缩小点,
改成内联会有效果吗??
2.内联后有啥负面影响吗?
(对查询,DML等的性能方面)
v10.1的版本
分享一:
Db2 支持单独存放大对象,也支持内联(INLINE)方式,将大对象字段数据和别的字段数据都存放在同一个页面中,但是LOB的大小受到Db2 Pagesize 的限制,超过页面大小还是会单独存放。如果您的LOB数据大多小于32K,建议使用32K的表空间,LOB INLINE方式,并且开启Db2 压缩,如果是联机系统,建议使用经典压缩(Static)方式,LOB数据通常会缩小2-3倍。由于Db2的交易日志是否压缩取决于表是否压缩,开启LOB INLINE并压缩后,数据库的日志也会缩小很多,对于该表的交易性能也会大幅提升。查询时,LOB INLINE通常也会提升性能,压缩后变小使得内存利用率更充分是一个方面,批量扫描数据时,可以顺序的将LOB读进Db2的bufferpool,效率高,单独存放时,每条记录中的LOB字段需要1次随机IO单独读取,导致性能低下,特别是是使用低性能磁盘的时候。
分享二:
缩小表可以使用压缩
lob是否可以inline存储取决于lob的实际长度,如果大于32K就无法使用inline存储了
使用inline存储性能会提高,没啥坏处
分享三:
首先,你的lob字段应该单独分离出来,你不管怎么改,如果和你的业务表混在一起,速度都不会有什么提升,在就是你改什么连接,你的条件不变,查出来的数据都不会改变,如何减少?
分享四:
可以考虑试试inline
08
有没有一些好用的db2数据库优化工具推荐?
IBM 官方的工具是DSM(Data Server Manager),包含数据库性能监控、数据库调优(OQWT, Optim Query Workload Tuner, 原来主机DB2上的查询调优工具)、配置变更管理(数据库参数变更、数据库对象定义变更)、数据库管理等功能。DSM支持历史性能数据管理,不仅仅是实时性能监控。另外,在实时性能监控上,db2top就是一个很好的工具,可以帮助定位很多性能问题。
09
分区表删除分区会不会出现索引失效的情况?
deatch 分区不会出现索引失效的情况。如果是分区索引(parttiitoned index,或本地索引),deatch分区成功后,被删除分区和数据立刻不可见;如果是非分区索引(not partitioned index,或全局索引),detach分区成功后,Db2采用了异步 清理的方式,将对应分区在全局索引上的页面进行清除处理,在清除期间,不影响对外提供服务,针对该表的DML操作依然可以正常进行。
10
容量很大的库,一般采取什么策略来进行清理?是定期删除,还是使用分区表?
对于数据库容量很大的库,一般采取什么策略来进行清理?是定期删除,还是使用分区表?不同的方案对日志需求,备份恢复策略有什么影响?
定期删除使用load还是delete的区别?
分享一:
数据清理的策略和业务直接相关,不一定按业务时间分区,清理时做分区detach就可以,在数据仓库和分析领域,历史数据归档通常却是可以采用分区detach方式的。
删除(delete)通常消耗大量的日志,而分区detach则不会。另外一个可选的方案是MDC fast rollout, 通过设置db2set DB2_MDC_ROLLOUT=DEFERRED实现,当delete 语句的where条件中只有MDC字段限定时,可以实现快速删除并且只记很少的日志。
对于联机系统,如果一次性删除大量数据可能导致锁升级,影响交易的并发性,建议多次小批量删除,通常的方法是多次执行:delete from (select * from <table name> where ... fetch first 10000 rows only);
detele不影响备份恢复策略;detach 是DDL操作,影响了表的定义,也就影响了表空间的MRT(Minimum Recovery Time),PIT恢复时必须恢复到detach操作时间点以后。
表清空可以采用load/import (load/import from /dev/null of del replace into <table name>) ,或是truncate (truncate table <table name> immediate), 或是关闭日志的操作(alter table <table name> activate not logged with empty table),也可以是是带任何条件的delete。除了delete需要记录大量的日志外,别的操作记录的日志很少或不记日志。
分享二:
第一,容量很大的必须用分区表
第二、删除的可以可以按分区删除,或者按分区归档数据。
分享三:
数据生命周期的管理是数据仓库(容量很大的库)的管理重点之一。
1.要有严格的建表审查机制,在表建立的时候就应对表的数据增长有预期,选择合适的表属性
2.对于大容量表,分区表是最合适的,卸载分区和重新挂载分区都很方便
3.很少有表会全部清空,所以如果不是分区表一般都在做delete
4.备份一般都是增量的,花的时间比删除还多
分享四:
采用分区表,以日期作为分区键,按分区的周期拆离分区
按这个方法跑了6年左右了,效果还行