oracle数据库突然变慢-oracle 几个大表join慢
当数据库变慢时,我们应该如何下手? 当应用管理员告知应用慢,数据库慢的时候,当Oracle DBA在数据库上做了几个sample Select,发现同样的问题时,有时候会无法Let's start,因为DBA认为各种seeding数据库的速率符合 Oracle 文档的建议。 事实上,今天的优化已经转变为优化等待。 在实践中,性能优化最根本的点也集中在I/O上。 库不足和操作系统某些资源的不合理使用是更好的方法。 让我与您分享一些实践经验。 本文重点介绍 Unix 环境。 第一章检查系统状态 通过操作系统的一些工具检查系统的状态,如CPU、内存、swap、磁盘利用率等,根据经验或与系统的正常状态进行比较,有时系统看起来表面上看好Idle,这可能不是正常状态,因为cpu可能在等待IO完成。 另外,还要注意占用系统资源(cpu、内存)的进程。 1.1 使用sar查看操作系统是否有IO问题 #sar -u 2 10 -- 即每2秒查看一次,共执行20次。 结果示例: 注意:在redhat下,%system就是所谓的%wio。 Linux 2.4.21-20.ELsmp (YY075) 05/19/2005 10:36:07 AM CPU %user %nice %system %idle10:36:09 AM all 0.00 0.00 0.13 99.8710:36:11 AM all 0.00 0.00 0.00 100.0 :36:13 AM 全部 0.25 0.00 0.25 99.4910:36:15 AM 全部 0.13 0.00 0.13 99.7510:36:17 AM 全部 0.00 0.00 0.00 100.00 其中: ? %usr是指用户进程占用cpu资源的百分比; ? %sys 指的是系统资源占用cpu资源的百分比; ? %wio是指等待io完成的百分比,值得注意; ? %idle 是闲置的百分比。
如果wio列的值很大,比如35%以上,说明系统的IO存在瓶颈oracle数据库突然变慢,CPU花费大量时间等待I/O完成。 Idle很小,说明系统CPU很忙。 像上面的例子,可以看到wio的平均值为11,说明I/O没有特别的问题,idle值为0,说明CPU满负荷运行。 当系统出现IO问题时,可以从以下几个方面来解决: 联系相应操作系统的技术支持进行这方面的优化,比如hp-ux在卷组划分时的条带化。 ? 发现Oracle中不合理的sql语句并优化; 合理分区。 1.2 常用的关注内存的工具是vmstat。 对于 hp-unix,可以使用 glance。 Aix 可以使用topas。 当发现vmstat中的pi列不为零oracle数据库突然变慢,内存中free列的值很小,glance和topas中的内存使用率都在80%以上,说明应该调整内存了. 方法一般有以下几项: ? 分配给Oracle的内存不要超过系统内存的1/2,一般保持在系统内存的40%为宜。 ? 增加系统内存; ? 如果你有很多连接,你可以使用MTS方法; ?
1.3 查找资源特别多的oracle session和它执行的语句,hp-unix可以用glance或top。 IBM AIX 可以使用 topas。 此外,您还可以使用 ps 命令。 通过这些程序可以查到这些占用系统资源较多的进程的进程号,可以通过下面的sql语句找出这个pid正在执行的是哪条sql。 这条sql最好在pl/sql developer、toad等软件中执行: SELECT a.username, a.machine, a.program, a.sid, a.serial#, a.status, c.piece, c.sql_text FROM v$session a, v$process b, v$sqltext cWHERE b.spid = 'ORCL'AND b.addr = a.paddrAND a.sql_address = c.address(+)ORDER BY c.piece; 可以分析获取到的sql,看其执行计划是否被索引。 通过优化避免全表扫描减少IO等待,从而加快语句执行速度。 提示:在优化sql的时候,经常会遇到使用in的语句,这时候一定要用exists代替,因为Oracle是按照Or的方式处理In的,即使使用索引也会很慢。 .
例如:SELECT col1, col2, col3 FROM table1 aWHERE a.col1 NOT IN (SELECT col1 FROM table2) 可以替换为:SELECT col1, col2, col3 FROM table1 aWHERE NOT EXISTS(SELECT 'x' FROM table2 b WHERE a. col1= b.col1)1.4 查找前十条性能较差的SQL语句 SELECT * FROM (SELECT parsing_user_id, executions, sorts, command_type, disk_reads, sql_text FROM v$sqlareaORDER BY disk_reads DESC) WHERE ROWNUM6AND st.wait_time=0AND st.event NOT LIKE '%SQL%'ORDER BY physical_reads DESC; 对检索结果的一些解释: 1. 以上是每个等待会话发生的物理读取的顺序,因为它与实际 I/O 相关。 2、可以看到这些等待进程在忙什么。 说法是否合理? SELECT sql_address FROM v$session WHERE sid=;SELECT * FROM v$sqltext WHERE address=; 执行上面两条语句,得到本次会话的语句。
您还可以使用 alter system kill session 'sid, serial#'; 杀死这个会话。 3、需要注意事件栏,是调优的重点栏。 下面简单说明一下频繁发生的事件: 1)buffer busy waits和free buffer waits这两个参数表示dbwr是否足够,和IO有很大关系。 当v$session_wait中的free buffer wait表项较小或没有表项时,说明系统的dbwr进程绝对充足,不需要调整; free buffer wait entry很多,系统肯定感觉很Slow,这个时候说明dbwr不够用了,它产生的wio就成了数据库性能的瓶颈。 此时解决方法如下: 增加写进程,调整db_block_lru_latches参数: 例:修改或增加以下两个参数 db_writer_processes =4db_block_lru_latches=8? 启用异步 IO。 IBM在这方面简单很多,而hp比较麻烦,可以联系HP工程师。 2)db file sequential read指的是顺序读,即全表扫描,尽量减少。 解决方法是使用索引和sql调优,同时增加参数db_file_multiblock_read_count。 3)db file scattered read参数是指通过索引读取,也可以通过增加参数db_file_multiblock_read_count来提升性能。 4) latch free与插头有关,需要特殊调整。 5) 其他参数无需特别注意。