首页 > 代码库 > 遇到 Form 性能问题怎么办 performance issue

遇到 Form 性能问题怎么办 performance issue

性能问题是比較复杂的问题. 一般由performance team 负责, 可是常见的情况是, 我们 INV team 定义的 view 不好, 导致查询性能较差. 这个必须由产品组和 performance team 一起来攻克了.

遇到性能问题的话, 几个经常使用的分析方法:

首先要找出性能较差的SQL, 这个要收集SQL trace, 然后转成 tkprof 文件来看.

把SQL 放到 pl/sql developer 里面, 查看运行计划. 非常多时候问题出在没有使用 index, 而是全表扫描了.

依照以下的步骤, 连接sqlplus, 一步一步运行, 生成 SQL trace 和 tkprof 文件. 里面会有更具体的信息.

BEGIN 
mo_global.set_policy_context('S', 204);
FND_GLOBAL.APPS_INITIALIZE (
 1068  
,56229 
,724
); 
END;

alter session set max_dump_file_size='UNLIMITED';
alter session set tracefile_identifier='APPSPERF';
alter session set events '10046 trace name context forever, level 12';
alter session set statistics_level = 'ALL';

ALTER SESSION SET NLS_LANGUAGE='AMERICAN';
ALTER SESSION SET NLS_LANGUAGE='SIMPLIFIED CHINESE';
select USERENV('LANG') from dual;

declare binds like below

   variable B1 number;
   variable B2 number;
   variable B3 number;
   variable B4 varchar2(50);
   variable B5 number;
   variable B6 number;
   
6. Assign values to binds

   begin
   :B1 := 2666;
   :B2 := 2666;
   :B3 := 2666;
   :B4 := 'VENDOR';
   :B5 := 8617;
   :B6 := 639187;
   end;
   /

7. Execute the test_SQL.sql WITH BIND VARIABLES (with :B1, :B2) 

8. exec dbms_session.reset_package;
9. exit completely from the sqlplus prompt.
10. SELECT value FROM v$parameter WHERE name ='user_dump_dest';
    go to this Dir and find (ls *APPSPERF*) --generated recently
11. Generate the tkprof of the trace generated with explain option.
12. provide TRACE,TKPROF and SQLTXTRACT(215187.1) to review it further. 


----------------------------------------------------2014-06-07 更新

这里讨论一下 tkprof 文件怎么看.

Rows (1st) Rows (avg) Rows (max)  Row Source Operation
---------- ---------- ----------  ---------------------------------------------------
    801471     801471     801471     FILTER  (cr=22258976 pr=56 pw=0 time=1382717063 us)
    801471     801471     801471      FILTER  (cr=22258973 pr=56 pw=0 time=1381082823 us)
    801471     801471     801471       NESTED LOOPS  (cr=22258973 pr=56 pw=0 time=1380590019 us)
    859012     859012     859012        NESTED LOOPS  (cr=23796 pr=45 pw=0 time=1831829 us cost=38 size=160 card=1)
      1701       1701       1701         NESTED LOOPS  (cr=2750 pr=0 pw=0 time=110268 us cost=19 size=122 card=1)
      1701       1701       1701          NESTED LOOPS  (cr=1037 pr=0 pw=0 time=64700 us cost=17 size=204 card=2)
      1701       1701       1701           NESTED LOOPS  (cr=1027 pr=0 pw=0 time=31038 us cost=13 size=324 card=4)
         4          4          4            TABLE ACCESS BY INDEX ROWID MTL_CC_SCHEDULE_REQUESTS (cr=4 pr=0 pw=0 time=180 us cost=4 size=106 card=2)
         4          4          4             INDEX RANGE SCAN MTL_CC_SCHEDULE_REQUESTS_N1 (cr=3 pr=0 pw=0 time=155 us cost=3 size=0 card=1)
      1701       1701       1701            TABLE ACCESS BY INDEX ROWID MTL_ONHAND_QUANTITIES_DETAIL (cr=1023 pr=0 pw=0 time=30010 us cost=7 size=56 card=2)
      1769       1769       1769             INDEX RANGE SCAN MTL_ONHAND_QUANTITIES_N4 (cr=45 pr=0 pw=0 time=5797 us cost=2 size=0 card=6)
      1701       1701       1701           TABLE ACCESS BY INDEX ROWID MTL_ITEM_LOCATIONS (cr=10 pr=0 pw=0 time=26007 us cost=1 size=21 card=1)
      1701       1701       1701            INDEX UNIQUE SCAN MTL_ITEM_LOCATIONS_U1 (cr=9 pr=0 pw=0 time=12782 us cost=0 size=0 card=1)
      1701       1701       1701          TABLE ACCESS BY INDEX ROWID MTL_SYSTEM_ITEMS_B (cr=1713 pr=0 pw=0 time=38392 us cost=1 size=20 card=1)
      1701       1701       1701           INDEX UNIQUE SCAN MTL_SYSTEM_ITEMS_B_U1 (cr=9 pr=0 pw=0 time=13686 us cost=0 size=0 card=1)
    859012     859012     859012         INDEX RANGE SCAN MTL_SERIAL_NUMBERS_N2 (cr=21046 pr=45 pw=0 time=1710013 us cost=3 size=0 card=123)
    801471     801471     801471        TABLE ACCESS BY INDEX ROWID MTL_SERIAL_NUMBERS (cr=22235177 pr=11 pw=0 time=1375657161 us cost=19 size=38 card=1)
  
这是一个典型的 tkprof 文件中面的运行计划. 我们能够看到这是有规律的缩进的. 看运行计划的原则是, 从中间往两边看.

首先看中间缩进最多的那一行: 这里用 index 訪问了 MTL_CC_SCHEDULE_REQUESTS 这个表, 选择了当中的 4 行.

         4          4          4            TABLE ACCESS BY INDEX ROWID MTL_CC_SCHEDULE_REQUESTS (cr=4 pr=0 pw=0 time=180 us cost=4 size=106 card=2)
         4          4          4             INDEX RANGE SCAN MTL_CC_SCHEDULE_REQUESTS_N1 (cr=3 pr=0 pw=0 time=155 us cost=3 size=0 card=1)
然后通过 MOQD 的 index 訪问了 MOQD, 选取了1701 行:

      1701       1701       1701            TABLE ACCESS BY INDEX ROWID MTL_ONHAND_QUANTITIES_DETAIL (cr=1023 pr=0 pw=0 time=30010 us cost=7 size=56 card=2)
      1769       1769       1769             INDEX RANGE SCAN MTL_ONHAND_QUANTITIES_N4 (cr=45 pr=0 pw=0 time=5797 us cost=2 size=0 card=6)
依据同样的规律, 终于訪问了 MTL_SERIAL_NUMBERS 这个表, 选取了801471 行.

    859012     859012     859012         INDEX RANGE SCAN MTL_SERIAL_NUMBERS_N2 (cr=21046 pr=45 pw=0 time=1710013 us cost=3 size=0 card=123)
    801471     801471     801471        TABLE ACCESS BY INDEX ROWID MTL_SERIAL_NUMBERS (cr=22235177 pr=11 pw=0 time=1375657161 us cost=19 size=38 card=1)
终于的结果就是第一行 FILTER 返回的行数, 也就是说, SQL 里面的这个FILTER 终于选择了801471 行:

Rows (1st) Rows (avg) Rows (max)  Row Source Operation
---------- ---------- ----------  ---------------------------------------------------
    801471     801471     801471     FILTER  (cr=22258976 pr=56 pw=0 time=1382717063 us)
从每一行后面的 time 我们能够看出来花在这一行上的时间有多少. 这里我们看到上面这个 FILTER 总共花了接近1400 秒, 20 分钟的样子. 非常久的时间.

上面举的样例是查询条件写的不好, 导致查询时间太长. 以下的样例是查询条件没有问题, 可是 index 建的不好, 导致没有使用索引而花了太多时间;

      1002       1002       1002                               TABLE ACCESS BY INDEX ROWID RCV_TRANSACTIONS (cr=34491 pr=34491 pw=0 time=140386031 us cost=13 size=274 card=1)
    124770     124770     124770                                INDEX RANGE SCAN RCV_TRANSACTIONS_N4 (cr=524 pr=524 pw=0 time=12869366 us cost=3 size=0 card=50)
我们看到, RT 这个表取出的行数是1002 行, 可是索引訪问了124770 行, 导致浪费了非常多时间. 因此须要依据查询条件, 又一次建立索引, 使索引訪问的行数和最后得到的行数接近甚至同样.

推断性能不好的还有一个方法是看 tkprof 文件里的

call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.22       0.21          0          0          0           0
Execute      1      1.84       1.83          0          0          0           0
Fetch        3   1106.09    1113.99        811     128069          0           4
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        5   1108.15    1116.04        811     128069          0           4
我们看到query 的行数 128069 比终于选取的行数 4 多了太多倍. 这是性能不好的一个标志.


上面两个样例, 第一个是查询条件写的不好, 查询了太多行. 这个是跟业务相关的代码, 须要我们自己去改动. 第二个样例中, 查询条件没有问题, 是索引建立的有问题, 须要依据须要又一次建立索引.

假设不知道如何建索引的话, 发邮件给performance team: appsperf_us@oracle.com. 他们会给你合适的建议.

Drop index PO.RCV_TRANSACTIONS_N4;
Create index PO.RCV_TRANSACTIONS_N4 on RCV_TRANSACTIONS(PO_HEADER_ID,VENDOR_ID);

遇到 Form 性能问题怎么办 performance issue