经常看到很多人费好大力气写好了SQL,但是执行效率很慢。一提到性能优化就挠头,四处寻求帮助。
其实如果了解哪些方面会影响oracle性能的话,这并不是一件难事。如果能够借助到第三方工具的帮助,那么性能优化简直就是傻瓜式的。
今天就誓将教会你如何利用object browser的功能来优化数据库性能。
- 一、Oracle统计信息的调整
一个运行良好的数据库,常常面临着数据量的增加而性能逐步恶化的困扰,性能问题通常被认为是由于磁盘容量或者内存等的规格引起的,
但实际上是由于SQL处理,也就是“实行计划”没有被正确编写引起的。
实行计划就是执行SQL时,数据库内部是怎样处理SQL的。
例如,是否使用索引,多张表存在的时候使用什么顺序结合等。
起初编写的实行计划并不一定是最好的。例如附加的索引没有被使用到。
记录的行数很少时,使用全面搜索更快一些,但如果使用索引,性能的问题就产生了。
那么,怎么才能正确的做成实行计划呢?
虽然有SQL的修正和追加索引等手段,但在这之前最重要的是“取得最新的统计信息”。
统计信息是记录各表的记录行数和数据分布的信息。
由于实行计划是基于统计信息决定的,随着数据的增加,性能下降,取得记录数等最新的统计信息,使实行计划最正确,提高性能。
使用SI Object Browser更新统计信息参照以下方法。
1.对象列表中,在表显示的状态下按“Ctrl+A”,选中所有表。(也可以选中处理较慢的SQL所参照的表。)
2.表被选中的状态下点击鼠标右键,选择“统计信息”。
3.统计信息画面显示出来,选中“修正正确的信息”,点击“OK”。
现在只支持Oracle版本,“在对象列表中表示详细信息”可以使详细信息在对象列表中显示。
选择“工具”菜单-->“选项”选项卡。
“对象列表”-->“表示对象固有的详细信息”设置成ON。
“表示”菜单-->“表示更新”。
这个设置有使表的记录数列表显示的优势。
统计信息的更新并不是对应用进行修正,更新统计信息之后还不能解决问题的话,建议使用SQL优化等其
他手段。我们接下来就讲一下SQL的优化。
- 二、SQL优化
SQL最优化就是“使内存得到最有效的利用”。
在数据库中有叫“程序库缓存”和“数据库缓冲”的内存区域,这些内存主要用于缓存。
把数据的读取作为例子,由于数据存储在硬盘的数据文件中,想要读取数据必须要有权限访问硬盘。
但是,第二次以后并不一定能使用缓存。由于内存大小是有限制的,当容量过大时则不能登录内存。或者缓存的数据将按照由旧到新的顺序被删除。
也就是说性能恶化的原因多数是由于数据增加,导致从访问内存转换到访问硬盘。活用内存缓存,使处理速度恢复到从前,这就是性能优化。
具体方法有增加内存,改变初始化参数等,也可以修改SQL文改善缓存。以下介绍两种方法。
使用提示句
不使用索引读取数据时(全表搜索),如果需要很大的内存导致不能访问缓存中的数据,缓存的功能就无效了。
SELECT /*+ INDEX (表名索引名)*/列名 FROM 表名
在SELECT的后面加上“/*+ INDEX (表名索引名)*/”。这样就可以明确的命令数据库“要使用索引”。
SI Object Browser中使用“实行计划”或者是“索引顾问”功能可以查询索引是否被使用,或者性能有多大的改善。
使用绑定变量
执行SQL时,数据库内部为了作成SQL实行计划必须要进行SQL解析,这样就会消耗CPU资源。
不把SELECT语句的WHERE条件和INSERT语句插入的各项目的值设置成固定值,而是像「SELECT * FROM SCOTT.EMP WHERE EMPNO = :EMPNO」这样把值的部分设置成变量。
//向Order表插入数据
SqlCommand cm = new SqlCommand(sql, cn);
stringsql = "INSERT INTO ORDER(";
sql += "OrderNo,";
sql += "CustomerNo,";
sql += "Price)";
sql += "VALUES ";
sql += "( @OrderNo ,";
sql += "@CustomerNo,";
sql += "@Price)";
cm.CommandText = sql;
//设置各绑定变量的值
cm.Parameters.Add(new SqlParameter("OrderNo", lblOrderNo.Text));
cm.Parameters.Add(new SqlParameter("CustomerNo", lblCustomerNo.ToString()));
cm.Parameters.Add(new SqlParameter("ShippingCharge", lblPrice.Text));
//实行SQL
cm.ExecuteNonQuery();
即使是这样还不能改善性能时,要考虑减轻访问硬盘的负荷,增加内存等方法。
- 三、让原因具体化
在Oracle中,发生等待时间原因的事件名和等待时间存在于字典视图中,调查下面的字典视图可以得到原因。
・V$SYSTEM_EVENT…显示数据库启动后发生的待机事件
・V$SESSION_EVENT…显示现行的session中全部的待机事件
・V$SESSION_WAIT…显示session正在待机中还是待机完了之后的事件
例如想要通过V$SYSTEM_EVENT调查时,使用以下的SQL文。
========================================================
SELECT EVENT, WAIT_CLASS, TOTAL_WAITS, AVERAGE_WAIT
FROM V$SYSTEM_EVENT
WHERE WAIT_CLASS ! = 'Idle'
========================================================
WAIT_CLASS列是'Idle'事件时,也就是空闲时间(等待用户请求的时间),不能作为性能恶化的原因,所以在WHERE中要除去'Idle'。
实行上述SQL后,EVENT列中表示事件名,TOTAL_WAITS列中表示总待机时间,AVERAGE_WAIT列中表示平均待机时间,这之中时间长的事件名就是性能恶化的原因。
下记是具有代表性的待机事件和解决方法。
1. db file scattered read/db file sequential read
通过全表搜索,索引搜索读取时发生。
【对策】改善SQL实行计划。
2. direct path write/direct path write temp
磁盘排序处理时花费的等待时间。
【对策】内存有效排序。
3.在“Library”中开始待机事件(log buffer space等)
与程序库缓冲关联的待机事件。
在载入工程的时间和多进程等同时访问时发生。
【对策】减少程序库缓存错误
4.在“log buffer”中开始待机事件(log buffer space等)
与日志文件关联的待机事件。Check point和写入慢时发生。
【对策】增加日志文件大小,增加日志文件组。
各种事件的详细内容请参照oracle以下讲解:
http://otndnld.oracle.co.jp/document/products/oracle11g/111/doc_dvd/server.111/E05771-04/waitevents.htm#12032
在V$SYSTEM_EVENT视图中记录了数据库从启动开始到现在的待机事件,有可能不能确定最近的性能恶化的原因。
这就是几乎全部有关oracle性能优化的基础了。
来源:oschina
链接:https://my.oschina.net/u/1157222/blog/143419