如何利用Object Browser图形化工具提高Oracle开发工作效率(四)提高数据库性能

海尼 发布于 2013/07/26 09:10
阅读 490
收藏 2
  • 想知道性能恶化的原因吗?这篇文章将教会你如何活用OB的功能来提高开发效率,优化数据库性能。我们将分三回来详细介绍。



    ■第一回:调整方法


    一个运行良好的数据库,常常面临着数据量的增加而性能逐步恶化的困扰,性能问题通常被认为是由于磁盘容量或者内存等的规格引起的,但实际上是由于SQL处理,也就是“实行计划”没有被正确编写引起的。

    实行计划就是执行SQL时,数据库内部是怎样处理SQL的。例如,是否使用索引,多张表存在的时候使用什么顺序结合等。起初编写的实行计划并不一定是最好的。例如附加的索引没有被使用到。记录的行数很少时,使用全面搜索更快一些,但如果使用索引,性能的问题就产生了。

    那么,怎么才能正确的做成实行计划呢?虽然有SQL的修正和追加索引等手段,但在这之前最重要的是“取得最新的统计信息”。统计信息是记录各表的记录行数和数据分布的信息。由于实行计划是基于统计信息决定的,随着数据的增加,性能下降,取得记录数等最新的统计信息,使实行计划最正确,提高性能。

    使用SI Object Browser更新统计信息参照以下方法。
    1.对象列表中,在表显示的状态下按“Ctrl+A”,选中所有表。(也可以选中处理较慢的SQL所参照的表。)
    2.表被选中的状态下点击鼠标右键,选择“统计信息”。
    3.统计信息画面显示出来,选中“修正正确的信息”,点击“OK”。

    现在只支持Oracle版本,“在对象列表中表示详细信息”可以使详细信息在对象列表中显示。
    选择“工具”菜单-->“选项”选项卡。
    “对象列表”-->“表示对象固有的详细信息”设置成ON。



    “表示”菜单-->“表示更新”。
    这个设置有使表的记录数一览表示的优势。



    统计信息的更新并不是对应用进行修正,更新统计信息之后还不能解决问题的话,建议使用SQL修正等其他手段。关于其他的方法,下回介绍。

    ■第二回:SQL最优化


    接上一回,继续进行“如何优化性能”。上回说性能恶化的原因多数是因为SQL,这次要说明怎样使SQL最优化。
    SQL最优化就是“使内存得到最有效的利用”。

    在数据库中有叫“程序库缓存”和“数据库缓冲”的内存区域,这些内存主要用于缓存。

    把数据的读取作为例子,由于数据存储在硬盘的数据文件中,想要读取数据必须要有权限访问硬盘。但是,读取硬盘上的文件需要时间,在数据库访问硬盘的时候,内存也在拷贝同样的数据,在第二次之后,只从内存就可以读取数据,提高了处理速度。这种结构就叫做缓存。

    但是,第二次以后并不一定能使用缓存。由于内存大小是有限制的,当容量过大时则不能登录内存。或者缓存的数据将按照由旧到新的顺序被删除。

    也就是说性能恶化的原因多数是由于数据增加,导致从访问内存转换到访问硬盘。活用内存缓存,使处理速度恢复到从前,这就是性能优化。

    具体方法有增加内存,改变初始化参数等,也可以修改SQL文改善缓存。以下介绍两种方法。

    使用提示句

    不使用索引读取数据时(全表搜索),如果需要很大的内存导致不能访问缓存中的数据,缓存的功能就无效了。 上回说到,“取得最新的统计信息”方法可以使实行计划得到改善,如果在SQL文中追加以下的提示句也许会更好。

    SELECT /*+ INDEX (表名索引名)*/列名 FROM 表名
    在SELECT的后面加上“/*+ INDEX (表名索引名)*/”。这样就可以明确的命令数据库“要使用索引”。

    SI Object Browser中使用“实行计划”或者是“索引顾问”功能可以查询索引是否被使用,或者性能有多大的改善。

    使用绑定变量

    执行SQL时,数据库内部为了作成SQL实行计划必须要进行SQL解析,这样就会消耗CPU资源。
    通常,SQL如果和过去实行过的SQL一样的话,通过程序库缓存就可以直接使用以前的解析结果。
    例如,「SELECT * FROM SCOTT.EMP WHERE EMPNO = 1」和「SELECT * FROM SCOTT.EMP WHERE EMPNO = 2」是不同的SQL,则不能使用缓存功能。

    不把SELECT语句的WHERE条件和INSERT语句插入的各项目的值设置成固定值,而是像「SELECT * FROM SCOTT.EMP WHERE EMPNO = :EMPNO」这样把值的部分设置成变量。这个变量就是绑定变量。使用绑定变量,因为SQL问变成了一样的,所以可以使用缓存功能。
    绑定变量还可以从存储过程,应用发行SQL。以下的代码是以C#为例子,也支持除此之外的主要的程序语言。

    //像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();

    即使是这样还不能改善性能时,要考虑减轻访问硬盘的负荷,增加内存等方法。首先要最优化比较容易的SQL。

    在最终回,会说明关于其他的性能问题产生的原因以及对策。

    ■第三回:让原因具体化


    上回说性能恶化的原因多数是因为SQL。接下来将要说明如果修正SQL还不能解决问题的话,使用其他的解决办法。

    在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和写入慢时发生。
    【对策】增加日志文件大小,增加日志文件组。

    各种事件的详细内容请参照一下网址:
    http://otndnld.oracle.co.jp/document/products/oracle11g/111/doc_dvd/server.111/E05771-04/waitevents.htm#12032
    在V$SYSTEM_EVENT视图中记录了数据库从启动开始到现在的待机事件,有可能不能确定最近的性能恶化的原因。这时,使用V$SESSION_EVENT视图,比较现象发生前和发生后的差别,就能得到确切的原因。性能恶化刚刚发生的话,也可以使用V$SESSION_WAIT。

    以上三回就是性能优化相关内容。性能优化看起来比较难,但是掌握了关键点的话谁都能操作。这次讲座如果能对大家有用的话,我们将非常荣幸。
加载中
返回顶部
顶部