这条select语句比较普通,目标表是一张partion by list的分区表:
SELECT TRIM(t.host_sys_id),TRIM(t.tran_code) INTO v_f_mbcode,v_netacct_data.v_srv_tancode FROM tranrechis t WHERE t.srv_trandate = v_srvdate AND t.srv_seq = v_srvseq;
在plsql developer的查询分析器中执行非常快。
SELECT TRIM(t.host_sys_id), TRIM(t.tran_code) -- INTO v_mbcode, nars.v_srv_tancode FROM t_channel_tranrechis t WHERE t.srv_trandate = '20120812' AND t.srv_seq = '00525488' call count cpu elapsed 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.00 0.00 0 4 0 1 ------- ------ -------- ---------- ---------- ---------- ---------- ---------- total 3 0.00 0.00 0 4 0 1 Misses in library cache during parse: 1 Optimizer mode: ALL_ROWS Parsing user id: 84 Number of plan statistics captured: 1 Rows (1st) Rows (avg) Rows (max) Row Source Operation ---------- ---------- ---------- --------------------------------------------------- 1 1 1 TABLE ACCESS BY GLOBAL INDEX ROWID T_CHANNEL_TRANRECHIS PARTITION: ROW LOCATION ROW LOCATION (cr=4 pr=0 pw=0 time=120 us cost=3 size=25 card=1) 1 1 1 INDEX UNIQUE SCAN T_CHANNEL_TRANRECHIS_IDX1 (cr=3 pr=0 pw=0 time=81 us cost=2 size=0 card=1)(object id 93786) Elapsed times include waiting on following events: Event waited on Times Max. Wait Total Waited ---------------------------------------- Waited ---------- ------------ SQL*Net message to client 2 0.00 0.00 SQL*Net message from client 2 0.00 0.00 ********************************************************************************
将同样的语句放入一个函数中,执行此函数,仍然非常快(对151条数据循环)。
SELECT TRIM(T.HOST_SYS_ID), TRIM(T.TRAN_CODE) FROM T_CHANNEL_TRANRECHIS T WHERE T.SRV_TRANDATE = :B2 AND T.SRV_SEQ = :B1 call count cpu elapsed disk query current rows ------- ------ -------- ---------- ---------- ---------- ---------- ---------- Parse 2 0.00 0.00 0 0 0 0 Execute 151 0.01 0.02 0 0 0 0 Fetch 151 0.00 0.00 0 604 0 151 ------- ------ -------- ---------- ---------- ---------- ---------- ---------- total 304 0.02 0.02 0 604 0 151 Misses in library cache during parse: 0 Misses in library cache during execute: 1 Optimizer mode: ALL_ROWS Parsing user id: 84 (recursive depth: 1) Number of plan statistics captured: 2 Rows (1st) Rows (avg) Rows (max) Row Source Operation ---------- ---------- ---------- --------------------------------------------------- 1 1 1 TABLE ACCESS BY GLOBAL INDEX ROWID T_CHANNEL_TRANRECHIS PARTITION: ROW LOCATION ROW LOCATION (cr=4 pr=0 pw=0 time=49 us cost=3 size=25 card=1) 1 1 1 INDEX UNIQUE SCAN T_CHANNEL_TRANRECHIS_IDX1 (cr=3 pr=0 pw=0 time=35 us cost=2 size=0 card=1)(object id 93786) ********************************************************************************
然而当把这条语句放入一个函数中,只执行1次,并且这个函数被另外一个函数重复调用151次时,却慢的出奇:
SQL ID: fr841k70ytha8 Plan Hash: 835389376 SELECT TRIM(T.HOST_SYS_ID), TRIM(T.TRAN_CODE) FROM T_CHANNEL_TRANRECHIS T WHERE T.SRV_TRANDATE = :B2 AND T.SRV_SEQ = :B1 call count cpu elapsed disk query current rows ------- ------ -------- ---------- ---------- ---------- ---------- ---------- Parse 1 0.00 0.00 0 0 0 0 Execute 151 0.01 0.01 0 0 0 0 Fetch 151 14.26 14.26 0 663041 604 151 ------- ------ -------- ---------- ---------- ---------- ---------- ---------- total 303 14.28 14.27 0 663041 604 151 Misses in library cache during parse: 0 Optimizer mode: ALL_ROWS Parsing user id: 84 (recursive depth: 1) Number of plan statistics captured: 1 Rows (1st) Rows (avg) Rows (max) Row Source Operation ---------- ---------- ---------- --------------------------------------------------- 1 1 1 PARTITION LIST ALL PARTITION: 1 12 (cr=4391 pr=0 pw=0 time=94409 us cost=1340 size=550 card=22) 1 1 1 TABLE ACCESS FULL T_CHANNEL_TRANRECHIS PARTITION: 1 12 (cr=4391 pr=0 pw=0 time=94387 us cost=1340 size=550 card=22) ********************************************************************************
为解决此问题,对其进行10046跟踪,结果发现两种形式的plsql 函数代码调用解析并不一致。对于第三种极慢的情况,用hints指定索引,或者加上分区key条件,效果都不理想。指定索引后,索引可生效,速度有所提高,例如:
******************************************************************************** SQL ID: bcwwpywas8sg7 Plan Hash: 3768379849 SELECT /*+index(t,t_channel_tranrechis_idx1)*/ TRIM(T.HOST_SYS_ID), TRIM(T.TRAN_CODE) FROM T_CHANNEL_TRANRECHIS T WHERE T.MONTH = SUBSTR(:B2 , 5, 2) AND T.SRV_TRANDATE = :B2 AND T.SRV_SEQ = :B1 call count cpu elapsed disk query current rows ------- ------ -------- ---------- ---------- ---------- ---------- ---------- Parse 1 0.00 0.00 0 0 0 0 Execute 151 0.02 0.01 0 0 0 0 Fetch 151 9.44 9.44 0 149188 0 151 ------- ------ -------- ---------- ---------- ---------- ---------- ---------- total 303 9.46 9.46 0 149188 0 151 Misses in library cache during parse: 0 Optimizer mode: ALL_ROWS Parsing user id: 84 (recursive depth: 1) Number of plan statistics captured: 1 Rows (1st) Rows (avg) Rows (max) Row Source Operation ---------- ---------- ---------- --------------------------------------------------- 1 1 1 TABLE ACCESS BY GLOBAL INDEX ROWID T_CHANNEL_TRANRECHIS PARTITION: ROW LOCATION ROW LOCATION (cr=988 pr=0 pw=0 time=63602 us cost=1012 size=28 card=1) 1 1 1 INDEX FULL SCAN T_CHANNEL_TRANRECHIS_IDX1 (cr=987 pr=0 pw=0 time=63089 us cost=993 size=0 card=22)(object id 93786) ********************************************************************************
但是提高并不明显,执行速度仍远远低于另外一个函数中直接使用的情况。最后,将被函数调用的函数的代码移入调用者函数,即不再函数调函数,而是跟第二种方式调用一样,这时执行速度才变成与第二种调用方式速度一样快。 问题解决,但又等于没有解决。究竟是什么原因影响了oracle对函数中select语句的解析呢?
原创文章,作者:苏葳,如需转载,请注明出处:https://www.swmemo.com/402.html