目录
1、调优的三大问题
2、调优的过程
3、调优的目标
5、调优的步骤
补充
6、性能和安全的权衡
1)哲学的三大问题和保安的三大问题是相同的:
(1)你是谁?
(2)你从那里来?
(3)你要到那里去?
2)调优的三大问题(3W):户外好,不做宅男宅女
(1)who? 谁来调
(2)why? 为什么调优
(3)how? 如何调
应用软件的开发流程:
需求分析->设计阶段->开发阶段->测试阶段->上线
调优是团队的责任。
需求分析师 |
弄清用户的需求和用户量,为系统的设计和实现打好基础。 |
系统设计师 |
应用逻辑性及应用的扩展性,数据库应用的架构(物理存储、逻辑存储、对象的架构),决定系统的根本问题。 |
开发人员 |
编写高效的代码,很大程度上影响系统的性能。 |
数据库管理员 |
负责调整数据库的参数,参与测试,配合开发人员对测试中出现的问题加以解决。DBA只能解决系统的一小部分问题。 |
系统管理员 |
调整操作系统的参数(关于内存、I/O、交换分区等) |
需求分析师十分关键,比如用户数算少了,系统就会负载的问题。
比如系统的统计模块结构没有设计好,程序有锁表的现象。物化视图。
开发人员写的经典代码:to_char(hiredate,'yyyy-mm-dd)>='2010-01-01'; --效率低,应该hiredate>=to_date('2010-01-01','yyyy-mm-dd');
DBA将JAVA程序访问的表和C程序访问的表放在同一个表空间。
系统管理员在系统上安装了另一个软件,占用大量内存,倒在内存溢出机器重启。
应用架构师负责应用的设计调整,程序员负责SQL语句开发的调整,这是最有用,效果最显著的调优手段。
DBA负责重新组织表的存储、索引管理、统计信息收集、创建柱状图、改变集簇因子等方法,让优化器选择最优的执行计划。
只有相互合作,才能把数据库调整到最优化状态。
3)为什么调优
为应用上线后有一个良好的运行环境。直观的现象——用户的抱怨。
调优可以分布到各个阶段:
1)应用的设计和开发阶段
2)数据库配置阶段:表空间及数据文件存储架构、表结构、索引等
3)新的应用上线
4)应用上线后故障排除和性能调整
补充:减少全表扫描的范围:用分区表(体系十一章table)
从变化入手:
比如系统突然慢下来了,问一下是否有新的应用添加了,日志有无突然加大,为什么会突然变慢。在看一下I/O是否性能下降了,发现了阵列的回写功能(写数据先写到缓冲区,不写磁盘,提高响应时间,回写功能必须有UPS的支持,3台电脑坏了两台,系统自动关闭回写,导致性能下降)。
调优的目标必须量化(不是越快越好),必须可见。
设定一个量化的目标(比如查询时间缩短到1min以内),达到目标后停止。
1)减少和消除等待事件
2)减少物理读(索引、索引组织表、簇、使用大尺寸块、物化视图、避免行迁移和行链接等、建立分区表)
3)常用的数据块缓存在内存,比如KEEP池,临时表
4)缩短响应时间
5)调整磁盘I/O检测热块,分布I/O
6)数据装载速度load(数据迁移)(并行、direct、nologging)
7)减少恢复时间(recovery,调整备份周期)
一定让用户能感受到调优后的改善之处,要可见,并可以量化。
unix分时系统,当cpu时间片用完后,进程处于等待状态。
处于等待状态的进程的数据,最好都放在内存中。如果进程越来越多,内存不够,等待状态的进程数据就会被挪到swap空间中,这个过程叫paging。内存如果过小,会导致交换现象——系统如果通过计算,发现如果调入某一个进程的数据而挤出其他进程的数据的代价反而比读磁盘中的swap区的代价更大,直接读磁盘,不读内存,就出问题了(内外存速度差1000倍)。
4、调优普遍问题
1)会话没有被释放:比如数据库的可用连接数越用越少。指定连接的限制条件和阀值。有人pl/sql直接点叉号关闭。有人退sqlplus喜欢用exit退出--用quit。开发人员(比如java)获取连接用完后不释放等坏习惯,连接池。
SQL> ! --!和exit是配套的,临时退出连接没有释放。
$ exit
exit
SQL>
2)游标设计问题:oltp系统中的sql语句的执行计划不被共享,硬解析较多,空间池紧张,需要游标共享(比如绑定变量)。数据仓库反而可以不共享。
游标就是一小块内存,就是个容器。我的游标打开很慢的优化例子。
3)表关联的设计——表设计遵循范式,减少表里面记录的冗余;如果进行一些反常规的设计,可以减少表与表连接所消耗的资源。
常见问题,比如老是进行多表连接,导致性能下降。
还有很多,比如sql的效率低下,代码的不规范等问题。
1)通过工具找出应用的瓶颈(操作系统:top、vmstat、iostat、topas、glance。database:EM、statspack、awr、rda、oracle的动态性能视图)
2)分析、判断造成瓶颈的原因
3)设定一个量化的目标,进行解决
4)检查问题是否解决,如果没有达到目标,继续第三步。达到目标就结束。
1)查看系统信息
$ top -n 5
top - 22:01:25 up 4:17, 4 users, load average: 0.18, 0.08, 0.02
Tasks: 147 total, 2 running, 145 sleeping, 0 stopped, 0 zombie
Cpu(s): 0.3%us, 0.3%sy, 0.0%ni, 99.3%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 2075500k total, 914528k used, 1160972k free, 65504k buffers
Swap: 4128760k total, 0k used, 4128760k free, 676824k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
3232 oracle 15 0 2340 1068 812 R 0.3 0.1 0:00.06 top
1 root 15 0 2072 616 532 S 0.0 0.0 0:00.91 init
2 root RT -5 0 0 0 S 0.0 0.0 0:00.00 migration/0
3 root 34 19 0 0 0 S 0.0 0.0 0:00.04 ksoftirqd/0
4 root RT -5 0 0 0 S 0.0 0.0 0:00.00 watchdog/0
5 root 10 -5 0 0 0 S 0.0 0.0 0:00.15 events/0
6 root 10 -5 0 0 0 S 0.0 0.0 0:00.07 khelper
7 root 10 -5 0 0 0 S 0.0 0.0 0:00.05 kthread
10 root 10 -5 0 0 0 S 0.0 0.0 0:01.51 kblockd/0
11 root 20 -5 0 0 0 S 0.0 0.0 0:00.00 kacpid
47 root 20 -5 0 0 0 S 0.0 0.0 0:00.00 cqueue/0
50 root 20 -5 0 0 0 S 0.0 0.0 0:00.00 khubd
52 root 10 -5 0 0 0 S 0.0 0.0 0:00.02 kseriod
114 root 15 0 0 0 0 S 0.0 0.0 0:00.00 pdflush
115 root 15 0 0 0 0 S 0.0 0.0 0:00.12 pdflush
116 root 20 -5 0 0 0 S 0.0 0.0 0:00.00 kswapd0
2)
$ vmstat 2 3 --2秒采一次样,循环显示3次
procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu------
r b swpd free buff cache si so bi bo in cs us sy id wa st
0 0 0 1161344 65624 676844 0 0 36 30 1044 117 0 1 99 0 0
0 0 0 1161344 65624 676868 0 0 0 120 1020 113 0 2 98 0 0
0 0 0 1161344 65632 676860 0 0 0 16 1013 103 0 1 99 0 0
(1)r 表示运行队列(就是说多少个进程真的分配到CPU),我测试的服务器目前CPU比较空闲,没什么程序在跑,当这个值超过了CPU数目,就会出现CPU瓶颈了。这个也和TOP的负载有关系,一般负载超过了3就比较高了,超过5就高,超过10就不正常了,服务器状态很危险。top的负载类似每秒的运行队列。如果运行队列过大,表示你的CPU很繁忙,一般会造成CPU使用率很高。
(2)b 表示阻塞的进程,进程阻塞
(3)swpd虚拟内存已使用的大小,如果大于0,表示你的机器物理内存不足了,如果不是程序内存泄漏的原因,那么你该升级内存了或者把耗内存的任务迁移到其他机器。
(4)free 空闲的物理内存的大小。
(5)buff:linux/Unix 系统是用来存储,目录里面有什么内容,权限等的缓存。
(6)cache:cache直接用来记忆我们打开的文件,给文件做缓冲,我本机大概占用300多M(这里是linux/unix的聪明之处,把空闲的物理内存的一部分拿来做文件和目录的缓存,是为了提高程序执行的性能,当程序使用内存时,buffer/cached会很快地被使用。)
(7)si:每秒从磁盘读入虚拟内存的大小,如果这个值大于0,表示物理内存不够用或者内存泄漏了,要查找耗内存进程解决掉。
(8)so:每秒虚拟内存写入磁盘的大小,如果这个值大于0,同上。
(9)bi:块设备每秒接收的块数量,这里的块设备是指系统上所有的磁盘和其他块设备,默认块大小是1024byte,我本机上没什么IO操作,所以一直是0。
(10)bo:块设备每秒发送的块数量,例如我们读取文件,bo就要大于0。bi和bo一般都要接近0,不然就是IO过于频繁,需要调整。
3)$ iostat -x 2 3 --没显示
1)控制文件多元化(控制文件如果太多,会增加对磁盘的I/O,两个或三个就可以)多元化三次比多换化两次,安全性高1000倍,是从安全性损坏概率角度来说。
2)日志组成员的多元化(没个日志组两个成员分别放到不同的磁盘上)
3)频繁生成检查点(频繁的检查点会增加磁盘的I/O)
4)数据文件备份(设计好的备份计划,使用增量备份)
5)启动归档(归档进程数、存放归档日志的磁盘I/O)
6)数据块检查
SQL> show parameter check
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
db_block_checking string FALSE --代价较高,一般为FALSE
db_block_checksum string TRUE --代价较低,根据块字节计算一个校验和
log_checkpoint_interval integer 0
log_checkpoint_timeout integer 1800
log_checkpoints_to_alert boolean FALSE
从文档中可以看到,db_block_checking 参数主要是用于数据块内逻辑(一致)检查(但只是块内,不包括块键的逻辑检查,比如索引项目的ROWID指向的是不存在的行等)主要用于防止在内存中损坏或数据损坏。由于是逻辑检查,因此引起的额外负荷比较高,甚至可以达到10%,因此对于一个繁忙的系统,特别是插入或更新操作很多的系统,性能影响是比较明显的。
该参数对SYSTEM表空间始终是处于“打开”状态,而不管该参数是否设置为FALSE。
可以看到,db_block_checksum只是在写入(DBWn常规写法或用户进程直接路径写入),根据一个CHECKSUM算法,计算数据块的校验和。然后写入数据块的一个特定位置(CACHE HEADER,具体是块的16-17字节,以0字节起算)。在读取块时,在进行检验。主要是防止IO硬件和IO子系统的错误。
CHECKSUM的算法只是根据块的字节值计算一个校验和,因此算法比较简单,引起的系统额外负荷通常在1%-2%
实际上,即使将该参数设为TRUE,将数据块(包括SYSTEM表空间)的16-17字节清0,同时将15字节(flag),第3位(即值为16进制0x04)清为0,则在块读取时也不会做CHECKSUM检查。如果该参数为FALSE,对于除SYSTEM的其他表空间,如果原来有CHECKSUM值,将15-16字节清0也不会做CHECKSUM检查。