性能问题是比較复杂的问题. 一般由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);