客户的应用是一个后台新闻发布系统,主要性能问题是通过连接访问新闻页极其缓慢,通常需要数据十秒才能返回。客户操作系统是SunOS 5.8,数据库版本
8.1.7
面对这个问题,首先想到是SQL问题,如何定位具体的问题SQL成为我们的主要目录,通过Statspack采样是一个全局手段,而能过SQL_TRACE则可以
实时对会话进行跟踪。
查询V$SESSION视图,获取进程信息:
SQL>select sid,serial#,username from v$session where username is not null;
然后对相应的应用会话启动SQL_TRACE跟踪:
SQL>exec dbms_system.set_sql_trace_in_session(7,284,true);
SQL>exec dbms_system.set_sql_trace_in_session(11,214,true);
SQL>exec dbms_system.set_sql_trace_in_session(16,1042,true);
应用执行一段时间后,关闭SQL_TRACE:
SQL>exec dbms_system.set_sql_trace_in_session(7,284,false);
SQL>exec dbms_system.set_sql_trace_in_session(11,214,false);
SQL>exec dbms_system.set_sql_trace_in_session(16,1042,false);
检查trace文件,可以找到跟踪过程中前台执行的SQL调用,检查发现以下语句是可疑的性能瓶颈点:
*********************************************************************
select auditstatus,...from cata.. a , categro b where b.id=a.categroryid and articaleId=2003... and auditstat > 0
call count cpu elspsed disk query current rows
-------------------------------------------------------------------------------------------------------------------------------
Parse 1 0.00 0.00 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 1 0.81 0.81 0 3892 0 1
-------------------------------------------------------------------------------------------------------------------------------
total 3 0.81 0.81 0 3892 0 1
这里的查询显示是根据articleId进行新闻读取的,但是注意到逻辑读有3892
查询执行计划确认该SQL为全表扫描
查询表结构是否存在索引
SQL>select index_name,table_name,column_name from user_ind_columns where table_name=upper('category...');
检查表结构:
SQL>desc cata..
因为ARTICLEID是一个字符型数据,查询中给入的articleId是一个数字值,Oracle发生潜在的数据类型转换,从面导致了索引失效:
SQL> select ... from cat... where articleId=...
Executoin Plan
------------------------------------------------------------------------------------------------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE(Cost=110 Card=2 Bytes=38)
1 0 TABLE ACCESS(FULL) OF ' CATA...' (Cost=110 Card=2 Bytes=38)
解决方法:只须在参数两侧各增加一个单引号,即可解决这个问题。