前一阵子优化了个SQL,原代码如下:
前一阵子,优化了一个SQL,原代码如下: create or replace package body CUX_INV_DEAD_STOCK_DETAIL_PKG is /* ================================================================================ * PROGRAM NAME: * CUX_INV_DEAD_STOCK_DETAIL_PKG * * PROGRAM STRUCTURE: * * ==============================================================================*/ g_error varchar2(500); g_debug varchar2(500); procedure outlog(g_message in varchar2) is begin fnd_file.PUT_LINE(fnd_file.LOG,g_message); end outlog; --输出日志 procedure output(g_message in varchar2) is begin fnd_file.PUT_LINE(fnd_file.OUTPUT,g_message); dbms_output.put_line(g_message); end output; --输出 /* ================================================================================= * FUNCTION / PROCEDURE * NAME : INV_DEAD_STOCK_DETAIL_MAIN * DESCRIPTION: CUX:呆滞物料统计表 * * ==================================================================================*/ procedure inv_dead_stock_detail_main(o_errcode out varchar2, o_errmess out varchar2, p_org_id in number, --业务实体 p_item_category in varchar2, --物料类型 p_inventory_item_f in varchar2, --物料从 p_inventory_item_t in varchar2, --物料至 p_dead_days in number --呆滞天数 ) is v_print_date varchar2(30); --打印日期 v_ou varchar2(30); --业务实体 v_item_category varchar2(100); --物料类型 v_inventory_item_f varchar2(100); --物料从 v_inventory_item_t varchar2(100); --物料至 v_dead_days varchar2(10); --呆滞天数 cursor c1 is select b.organization_id, b.item_category, b.item_sub_category, b.segment1, b.description, b.primary_unit_of_measure, b.item_cost, b.onhand_quantity, b.onhand_amount, b.last_transaction_date, b.dead_stock_days from (select a.organization_id, a.item_category, a.item_sub_category, a.segment1, a.description, a.primary_unit_of_measure, a.item_cost, a.onhand_quantity, a.onhand_amount, max(mmt.transaction_date) last_transaction_date, trunc(sysdate - max(mmt.transaction_date)) dead_stock_days from mtl_material_transactions mmt, (select msib.organization_id, msib.inventory_item_id, mcb.segment1 item_category, --物料大类 mcb.segment2 item_sub_category, --物料小类 msib.segment1, msib.description, --onhand.transaction_uom_code, msib.primary_unit_of_measure, cic.item_cost, sum(onhand.transaction_quantity) onhand_quantity, (cic.item_cost * sum(onhand.transaction_quantity)) onhand_amount from mtl_system_items_b msib, cst_item_costs cic, mtl_categories_b mcb, mtl_item_categories mic, mtl_onhand_quantities_detail onhand where 1 = 1 and msib.inventory_item_id = onhand.inventory_item_id and msib.organization_id = onhand.organization_id and onhand.inventory_item_id = cic.inventory_item_id and onhand.organization_id = cic.organization_id and mcb.category_id = mic.category_id and mic.inventory_item_id=msib.inventory_item_id and mic.organization_id=msib.organization_id and mcb.structure_id = 101 and mic.category_set_id = 1 and cic.cost_type_id = 3 and onhand.organization_id = p_org_id --and msib.inventory_item_id=3073 and mcb.segment2=nvl(p_item_category,mcb.segment2) and substr(onhand.subinventory_code,1,1)not in ('E','B') and msib.segment1 between nvl(p_inventory_item_f,msib.segment1) and nvl(p_inventory_item_t,msib.segment1) group by msib.organization_id, msib.inventory_item_id, mcb.segment1, mcb.segment2, msib.segment1, msib.description, msib.primary_unit_of_measure, cic.item_cost) a where 1 = 1 and a.organization_id = mmt.organization_id and a.inventory_item_id = mmt.inventory_item_id and mmt.transaction_type_id <>24 group by a.organization_id, a.item_category, a.item_sub_category, a.segment1, a.description, a.primary_unit_of_measure, a.item_cost, a.onhand_quantity, a.onhand_amount) b where b.dead_stock_days > nvl(p_dead_days,0); begin --处理报表头信息 g_debug := '初始化公司LOGO和输入条件'; --获取打印日期 select to_char(sysdate,'YYYY-MM-DD HH24:MI:SS') into v_print_date from dual; --获取业务实体 select trim(hou.name) into v_ou from hr_operating_units hou where hou.organization_id = p_org_id; --获取物料类型 v_item_category:=trim(p_item_category); --获取物料从 v_inventory_item_f:=trim(p_inventory_item_f); --获取物料至 v_inventory_item_t:=trim(p_inventory_item_t); --获取物料呆滞天数 v_dead_days:=to_char(p_dead_days); --开始输出报表头信息 g_debug :='输出打印日期和用户输入条件'; output('<?xml version="1.0" encoding="UTF-8"?> <!-- Generated by Oracle Reports version 10.1.2.3.0 --> <CUXINVDEADSTOCK> <LIST_G_REPORT>'); output('<PRINT_DATE>' || v_print_date || '</PRINT_DATE>'); output('<OU>' || v_ou || '</OU>'); output('<ITEM_CATEGORY>' || v_item_category || '</ITEM_CATEGORY>'); output('<INVENTORY_ITEM_F>' || v_inventory_item_f || '</INVENTORY_ITEM_F>'); output('<INVENTORY_ITEM_T>' || v_inventory_item_t || '</INVENTORY_ITEM_T>'); output('<DEAD_DAYS>' || v_dead_days || '</DEAD_DAYS>'); --主体数据内循环开始 g_debug :='主体数据内循环开始'; for c1r in c1 loop output('<G_REPORT>'); output('<CATEGORY_CODE>' || c1r.item_category ||'.'|| c1r.item_sub_category || '</CATEGORY_CODE>'); output('<ITEM_CODE>' || c1r.segment1 || '</ITEM_CODE>'); output('<ITEM_DESCRIPTION>' || cux_common_pkg.Xml_Format(c1r.description) || '</ITEM_DESCRIPTION>'); output('<ITEM_UOM>' || c1r.primary_unit_of_measure || '</ITEM_UOM>'); output('<ITEM_ONHAND>' || c1r.Onhand_Quantity || '</ITEM_ONHAND>'); output('<LAST_TRANSACTION>' || to_char(c1r.last_transaction_date,'YYYY-MM-DD HH24:MI:SS') || '</LAST_TRANSACTION>'); output('<DEAD_STOCK_DAYS>' || c1r.Dead_Stock_Days || '</DEAD_STOCK_DAYS>'); output('<ITEM_COST>' || c1r.Item_Cost || '</ITEM_COST>'); output('<ONHAND_AMOUNT>' || c1r.onhand_amount || '</ONHAND_AMOUNT>'); output('</G_REPORT>'); end loop; output('</LIST_G_REPORT>'); output('</CUXINVDEADSTOCK>'); exception when others then g_error := SQLERRM; INSERT INTO session_log --记录异常信息到异常表 VALUES (SYSDATE, 'INVENTORY', 'CUX_INV_DEAD_STOCK_DETAIL_PKG', g_debug, g_error); COMMIT; outlog('出现错误'); end inv_dead_stock_detail_main; end CUX_INV_DEAD_STOCK_DETAIL_PKG;
这段代码运行的环境是oracle EBS R12中的一个查询呆滞物料的报表,运行的环境为IBM小机P系列(印象中应该P750)+v7000存储,这个报表跑出来的时间是最长达35分钟,在另一个低点的测试环境中用了将近七小时(具体配置就不提了),用10046 trace 出来的结果为(只取其中的主要的一段):
SELECT B.ORGANIZATION_ID, B.ITEM_CATEGORY, B.ITEM_SUB_CATEGORY, B.SEGMENT1, B.DESCRIPTION, B.PRIMARY_UNIT_OF_MEASURE, B.ITEM_COST, B.ONHAND_QUANTITY, B.ONHAND_AMOUNT, B.LAST_TRANSACTION_DATE, B.DEAD_STOCK_DAYS FROM (SELECT A.ORGANIZATION_ID, A.ITEM_CATEGORY, A.ITEM_SUB_CATEGORY, A.SEGMENT1, A.DESCRIPTION, A.PRIMARY_UNIT_OF_MEASURE, A.ITEM_COST, A.ONHAND_QUANTITY, A.ONHAND_AMOUNT, MAX(MMT.TRANSACTION_DATE) LAST_TRANSACTION_DATE, TRUNC(SYSDATE - MAX(MMT.TRANSACTION_DATE)) DEAD_STOCK_DAYS FROM MTL_MATERIAL_TRANSACTIONS MMT, (SELECT MSIB.ORGANIZATION_ID, MSIB.INVENTORY_ITEM_ID, MCB.SEGMENT1 ITEM_CATEGORY, MCB.SEGMENT2 ITEM_SUB_CATEGORY, MSIB.SEGMENT1, MSIB.DESCRIPTION, MSIB.PRIMARY_UNIT_OF_MEASURE, CIC.ITEM_COST, SUM(ONHAND.TRANSACTION_QUANTITY) ONHAND_QUANTITY, (CIC.ITEM_COST * SUM(ONHAND.TRANSACTION_QUANTITY)) ONHAND_AMOUNT FROM MTL_SYSTEM_ITEMS_B MSIB, CST_ITEM_COSTS CIC, MTL_CATEGORIES_B MCB, MTL_ITEM_CATEGORIES MIC, MTL_ONHAND_QUANTITIES_DETAIL ONHAND WHERE 1 = 1 AND MSIB.INVENTORY_ITEM_ID = ONHAND.INVENTORY_ITEM_ID AND MSIB.ORGANIZATION_ID = ONHAND.ORGANIZATION_ID AND ONHAND.INVENTORY_ITEM_ID = CIC.INVENTORY_ITEM_ID AND ONHAND.ORGANIZATION_ID = CIC.ORGANIZATION_ID AND MCB.CATEGORY_ID = MIC.CATEGORY_ID AND MIC.INVENTORY_ITEM_ID=MSIB.INVENTORY_ITEM_ID AND MIC.ORGANIZATION_ID=MSIB.ORGANIZATION_ID AND MCB.STRUCTURE_ID = 101 AND MIC.CATEGORY_SET_ID = 1 AND CIC.COST_TYPE_ID = 3 AND ONHAND.ORGANIZATION_ID = :B4 AND MCB.SEGMENT2=NVL(:B3 ,MCB.SEGMENT2) AND SUBSTR(ONHAND.SUBINVENTORY_CODE,1,1)NOT IN ('E','B') AND MSIB.SEGMENT1 BETWEEN NVL(:B2 ,MSIB.SEGMENT1) AND NVL(:B1 ,MSIB.SEGMENT1) GROUP BY MSIB.ORGANIZATION_ID, MSIB.INVENTORY_ITEM_ID, MCB.SEGMENT1, MCB.SEGMENT2, MSIB.SEGMENT1, MSIB.DESCRIPTION, MSIB.PRIMARY_UNIT_OF_MEASURE, CIC.ITEM_COST) A WHERE 1 = 1 AND A.ORGANIZATION_ID = MMT.ORGANIZATION_ID AND A.INVENTORY_ITEM_ID = MMT.INVENTORY_ITEM_ID AND MMT.TRANSACTION_TYPE_ID <>24 GROUP BY A.ORGANIZATION_ID, A.ITEM_CATEGORY, A.ITEM_SUB_CATEGORY, A.SEGMENT1, A.DESCRIPTION, A.PRIMARY_UNIT_OF_MEASURE, A.ITEM_COST, A.ONHAND_QUANTITY, A.ONHAND_AMOUNT) B WHERE B.DEAD_STOCK_DAYS > NVL(:B5 ,0) 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 259.38 7987.81 1336813 28643548 0 0 ------- ------ -------- ---------- ---------- ---------- ---------- ---------- total 3 259.38 7987.81 1336813 28643548 0 0 Misses in library cache during parse: 0 Optimizer goal: ALL_ROWS Parsing user id: 44 (recursive depth: 1) Rows Row Source Operation ------- --------------------------------------------------- 0 FILTER (cr=0 pr=0 pw=0 time=0 us) 0 HASH GROUP BY (cr=0 pr=0 pw=0 time=0 us cost=408 size=138 card=1) 2382290 NESTED LOOPS (cr=28643548 pr=1336813 pw=0 time=7771837034 us) 2384353 NESTED LOOPS (cr=26956486 pr=38996 pw=0 time=133943370 us cost=407 size=4968 card=36) 4323 VIEW (cr=26927194 pr=19148 pw=0 time=51978 us cost=377 size=118 card=1) 4323 HASH GROUP BY (cr=26927194 pr=19148 pw=0 time=32507 us) 39226 CONCATENATION (cr=26927194 pr=19148 pw=0 time=200800799 us) 39226 FILTER (cr=26927194 pr=19148 pw=0 time=200782622 us) 39226 NESTED LOOPS (cr=26927194 pr=19148 pw=0 time=200762465 us) 39226 NESTED LOOPS (cr=26874154 pr=13992 pw=0 time=169916397 us cost=261 size=152 card=1) 39249 NESTED LOOPS (cr=26795777 pr=9888 pw=0 time=150089655 us cost=259 size=134 card=1) 4592133 NESTED LOOPS (cr=17625783 pr=6874 pw=0 time=110462727 us cost=247 size=1368 card=12) 4592133 MERGE JOIN CARTESIAN (cr=10739 pr=402 pw=0 time=6150125 us cost=223 size=612 card=12) 117 TABLE ACCESS BY INDEX ROWID MTL_CATEGORIES_B (cr=11 pr=10 pw=0 time=17429 us cost=4 size=34 card=1) 117 INDEX RANGE SCAN MTL__CATEGORIES_B_N2 (cr=1 pr=1 pw=0 time=560 us cost=1 size=0 card=29)(object id 118829) 4592133 BUFFER SORT (cr=10728 pr=392 pw=0 time=4082113 us cost=219 size=884 card=52) 39249 TABLE ACCESS BY INDEX ROWID MTL_ONHAND_QUANTITIES_DETAIL (cr=10728 pr=392 pw=0 time=709319 us cost=219 size=884 card=52) 39249 INDEX RANGE SCAN MTL_ONHAND_QUANTITIES_N5 (cr=385 pr=385 pw=0 time=575783 us cost=204 size=0 card=52)(object id 120237) 4592133 TABLE ACCESS BY INDEX ROWID MTL_SYSTEM_ITEMS_B (cr=17615044 pr=6472 pw=0 time=0 us cost=2 size=63 card=1) 4592133 INDEX UNIQUE SCAN MTL_SYSTEM_ITEMS_B_U1 (cr=9171958 pr=1125 pw=0 time=0 us cost=1 size=0 card=1)(object id 120986) 39249 INDEX UNIQUE SCAN MTL_ITEM_CATEGORIES_U1 (cr=9169994 pr=3014 pw=0 time=0 us cost=1 size=20 card=1)(object id 119585) 39226 INDEX UNIQUE SCAN CST_ITEM_COSTS_U1 (cr=78377 pr=4104 pw=0 time=0 us cost=1 size=0 card=1)(object id 208817) 39226 TABLE ACCESS BY INDEX ROWID CST_ITEM_COSTS (cr=53040 pr=5156 pw=0 time=0 us cost=2 size=18 card=1) 0 FILTER (cr=0 pr=0 pw=0 time=0 us) 0 NESTED LOOPS (cr=0 pr=0 pw=0 time=0 us) 0 NESTED LOOPS (cr=0 pr=0 pw=0 time=0 us cost=115 size=152 card=1) 0 NESTED LOOPS (cr=0 pr=0 pw=0 time=0 us cost=113 size=134 card=1) 0 NESTED LOOPS (cr=0 pr=0 pw=0 time=0 us cost=110 size=117 card=1) 0 MERGE JOIN CARTESIAN (cr=0 pr=0 pw=0 time=0 us cost=46 size=6208 card=64) 0 TABLE ACCESS BY INDEX ROWID MTL_CATEGORIES_B (cr=0 pr=0 pw=0 time=0 us cost=4 size=34 card=1) 0 INDEX RANGE SCAN MTL__CATEGORIES_B_N2 (cr=0 pr=0 pw=0 time=0 us cost=1 size=0 card=29)(object id 118829) 0 BUFFER SORT (cr=0 pr=0 pw=0 time=0 us cost=42 size=17262 card=274) 0 TABLE ACCESS BY INDEX ROWID MTL_SYSTEM_ITEMS_B (cr=0 pr=0 pw=0 time=0 us cost=42 size=17262 card=274) 0 INDEX RANGE SCAN MTL_SYSTEM_ITEMS_B_U2 (cr=0 pr=0 pw=0 time=0 us cost=7 size=0 card=49)(object id 408422) 0 INDEX UNIQUE SCAN MTL_ITEM_CATEGORIES_U1 (cr=0 pr=0 pw=0 time=0 us cost=1 size=20 card=1)(object id 119585) 0 TABLE ACCESS BY INDEX ROWID MTL_ONHAND_QUANTITIES_DETAIL (cr=0 pr=0 pw=0 time=0 us cost=3 size=17 card=1) 0 INDEX RANGE SCAN MTL_ONHAND_QUANTITIES_N4 (cr=0 pr=0 pw=0 time=0 us cost=2 size=0 card=1)(object id 120239) 0 INDEX UNIQUE SCAN CST_ITEM_COSTS_U1 (cr=0 pr=0 pw=0 time=0 us cost=1 size=0 card=1)(object id 208817) 0 TABLE ACCESS BY INDEX ROWID CST_ITEM_COSTS (cr=0 pr=0 pw=0 time=0 us cost=2 size=18 card=1) 2384353 INDEX RANGE SCAN MTL_MATERIAL_TRANSACTIONS_N1 (cr=29292 pr=19848 pw=0 time=97162036 us cost=3 size=0 card=41)(object id 119944) 2382290 TABLE ACCESS BY INDEX ROWID MTL_MATERIAL_TRANSACTIONS (cr=1687062 pr=1297817 pw=0 time=0 us cost=31 size=720 card=36) Elapsed times include waiting on following events: Event waited on Times Max. Wait Total Waited ---------------------------------------- Waited ---------- ------------ db file sequential read 1336813 0.64 7789.24 latch free 1 0.00 0.00
从上面的执行计划中可以看到,大量的nested loops中逻辑读与物理读很大,而在外层嵌套中表
MTL_MATERIAL_TRANSACTIONS的数据量大,消耗的时间7771,837034us 即将近七小时,改写方案如下: 1.先创建临时表,用来存放内层结果: 2.将传进来的参数作判断处理, 3.将最外层表与内层结果用hash 返回结果; 结果如下: CREATE GLOBAL TEMPORARY TABLE CUX.DEAD_MT ( ORGANIZATION_ID NUMBER, --MSIB_ORGANIZATION_ID INVENTORY_ITEM_ID NUMBER, --MSIB_INVENTORY_ITEM_ID item_category VARCHAR2(40 BYTE), -- MCB_SEGMENT1 item_category, --物料大类 item_sub_category VARCHAR2(40 BYTE), -- MCB_SEGMENT2 item_sub_category, --物料小类 SEGMENT1 VARCHAR2(40 BYTE), --MSIB_SEGMENT1 DESCRIPTION VARCHAR2(240 BYTE), --MSIB_DESCRIPTION PRIMARY_UNIT_OF_MEASURE VARCHAR2(25 BYTE), --MSIB_PRIMARY_UNIT_OF_MEASURE ITEM_COST NUMBER, --CIC_ITEM_COST ONHAND_QUANTITY NUMBER, --sum(onhand.transaction_quantity) onhand_quantity, ONHAND_AMOUNT NUMBER --(cic.item_cost * sum(onhand.transaction_quantity)) ) ON COMMIT DELETE ROWS; create or replace package body CUX_INV_DEAD_STOCK_DETAIL_PKG is /* ================================================================================ * PROGRAM NAME: * CUX_INV_DEAD_STOCK_DETAIL_PKG * * ==============================================================================*/ g_error varchar2(500); g_debug varchar2(500); procedure outlog(g_message in varchar2) is begin fnd_file.PUT_LINE(fnd_file.LOG,g_message); end outlog; --输出日志 procedure output(g_message in varchar2) is begin fnd_file.PUT_LINE(fnd_file.OUTPUT,g_message); dbms_output.put_line(g_message); end output; --输出 /* ================================================================================= * FUNCTION / PROCEDURE * NAME : INV_DEAD_STOCK_DETAIL_MAIN * * ==================================================================================*/ procedure inv_dead_stock_detail_main(o_errcode out varchar2, o_errmess out varchar2, p_org_id in number, --业务实体 p_item_category in varchar2, --物料类型 p_inventory_item_f in varchar2, --物料从 p_inventory_item_t in varchar2, --物料至 p_dead_days in number --呆滞天数 ) is v_print_date varchar2(30); --打印日期 v_ou varchar2(30); --业务实体 v_item_category varchar2(100); --物料类型 v_inventory_item_f varchar2(100); --物料从 v_inventory_item_t varchar2(100); --物料至 v_dead_days varchar2(10); --呆滞天数 cursor c1 is select b.organization_id, b.item_category, b.item_sub_category, b.segment1, b.description, b.primary_unit_of_measure, b.item_cost, b.onhand_quantity, b.onhand_amount, b.last_transaction_date, b.dead_stock_days from( select /*+use_hash(mmt ,a)*/ a.ORGANIZATION_ID, a.item_category, -- a.INVENTORY_ITEM_ID, a.item_sub_category, a.segment1, a.description, a.primary_unit_of_measure, a.item_cost, a.onhand_quantity, a.onhand_amount, max(mmt.transaction_date) last_transaction_date, trunc(TO_DATE('2015-3-30 11:36:00','YYYY-MM-DD HH24:MI:SS') - max(mmt.transaction_date)) dead_stock_days --trunc(sysdate - max(mmt.transaction_date)) dead_stock_days from mtl_material_transactions mmt, DEAD_MT a where 1 = 1 and a.organization_id = mmt.organization_id and a.inventory_item_id = mmt.inventory_item_id and mmt.transaction_type_id <>24 and a.item_sub_category=nvl(p_item_category,a.item_sub_category) --and a.segment1 between nvl(null,a.segment1) and nvl(null,a.segment1) group by a.organization_id, a.item_category, a.item_sub_category, a.segment1, a.description, a.primary_unit_of_measure, a.item_cost, a.onhand_quantity, a.onhand_amount) b where b.dead_stock_days > nvl(p_dead_days,0); begin if (p_inventory_item_f is null and p_inventory_item_t is null) then insert /* +append*/into DEAD_MT select msib.organization_id, msib.inventory_item_id, mcb.segment1 item_category, --物料大类 mcb.segment2 item_sub_category, --物料小类 msib.segment1, msib.description, --onhand.transaction_uom_code, msib.primary_unit_of_measure, cic.item_cost, sum(onhand.transaction_quantity) onhand_quantity, (cic.item_cost * sum(onhand.transaction_quantity)) onhand_amount from mtl_system_items_b msib, cst_item_costs cic, mtl_categories_b mcb, mtl_item_categories mic, mtl_onhand_quantities_detail onhand where 1=1 and msib.inventory_item_id = onhand.inventory_item_id and msib.organization_id = onhand.organization_id and onhand.inventory_item_id = cic.inventory_item_id and onhand.organization_id = cic.organization_id and mcb.category_id = mic.category_id and mic.inventory_item_id=msib.inventory_item_id and mic.organization_id=msib.organization_id and mcb.structure_id = 101 and mic.category_set_id = 1 and cic.cost_type_id = 3 and onhand.organization_id = p_org_id --and msib.inventory_item_id=3073 -- and mcb.segment2=nvl(null,mcb.segment2) and mcb.segment2=nvl(p_item_category,mcb.segment2) and substr(onhand.subinventory_code,1,1)not in ('E','B') -- and msib.segment1 between nvl(null,msib.segment1) and nvl(null,msib.segment1) -- and msib.segment1 between nvl(p_inventory_item_f,msib.segment1) and nvl(p_inventory_item_t,msib.segment1) group by msib.organization_id, msib.inventory_item_id, mcb.segment1, mcb.segment2, msib.segment1, msib.description, msib.primary_unit_of_measure, cic.item_cost; end if; if ( p_inventory_item_f is not null and p_inventory_item_t is not null) then insert into DEAD_MT select msib.organization_id, msib.inventory_item_id, mcb.segment1 item_category, --物料大类 mcb.segment2 item_sub_category, --物料小类 msib.segment1, msib.description, --onhand.transaction_uom_code, msib.primary_unit_of_measure, cic.item_cost, sum(onhand.transaction_quantity) onhand_quantity, (cic.item_cost * sum(onhand.transaction_quantity)) onhand_amount from mtl_system_items_b msib, cst_item_costs cic, mtl_categories_b mcb, mtl_item_categories mic, mtl_onhand_quantities_detail onhand where 1=1 and msib.inventory_item_id = onhand.inventory_item_id and msib.organization_id = onhand.organization_id and onhand.inventory_item_id = cic.inventory_item_id and onhand.organization_id = cic.organization_id and mcb.category_id = mic.category_id and mic.inventory_item_id=msib.inventory_item_id and mic.organization_id=msib.organization_id and mcb.structure_id = 101 and mic.category_set_id = 1 and cic.cost_type_id = 3 and onhand.organization_id = p_org_id --and msib.inventory_item_id=3073 --and mcb.segment2=nvl(null,mcb.segment2) --and mcb.segment2=p_item_category and substr(onhand.subinventory_code,1,1)not in ('E','B') -- and msib.segment1 between nvl(null,msib.segment1) and nvl(null,msib.segment1) and msib.segment1 between p_inventory_item_f and p_inventory_item_t group by msib.organization_id, msib.inventory_item_id, mcb.segment1, mcb.segment2, msib.segment1, msib.description, msib.primary_unit_of_measure, cic.item_cost; end if; if ( p_inventory_item_f is not null and p_inventory_item_t is null) then insert into DEAD_MT select msib.organization_id, msib.inventory_item_id, mcb.segment1 item_category, --物料大类 mcb.segment2 item_sub_category, --物料小类 msib.segment1, msib.description, --onhand.transaction_uom_code, msib.primary_unit_of_measure, cic.item_cost, sum(onhand.transaction_quantity) onhand_quantity, (cic.item_cost * sum(onhand.transaction_quantity)) onhand_amount from mtl_system_items_b msib, cst_item_costs cic, mtl_categories_b mcb, mtl_item_categories mic, mtl_onhand_quantities_detail onhand where 1=1 and msib.inventory_item_id = onhand.inventory_item_id and msib.organization_id = onhand.organization_id and onhand.inventory_item_id = cic.inventory_item_id and onhand.organization_id = cic.organization_id and mcb.category_id = mic.category_id and mic.inventory_item_id=msib.inventory_item_id and mic.organization_id=msib.organization_id and mcb.structure_id = 101 and mic.category_set_id = 1 and cic.cost_type_id = 3 and onhand.organization_id = p_org_id --and msib.inventory_item_id=3073 --and mcb.segment2=nvl(null,mcb.segment2) and mcb.segment2=p_item_category and substr(onhand.subinventory_code,1,1)not in ('E','B') -- and msib.segment1 between nvl(null,msib.segment1) and nvl(null,msib.segment1) and msib.segment1 between p_inventory_item_f and msib.segment1 group by msib.organization_id, msib.inventory_item_id, mcb.segment1, mcb.segment2, msib.segment1, msib.description, msib.primary_unit_of_measure, cic.item_cost; end if; --处理报表头信息 g_debug := '初始化公司LOGO和输入条件'; --获取打印日期 select to_char(sysdate,'YYYY-MM-DD HH24:MI:SS') into v_print_date from dual; --获取业务实体 select trim(hou.name) into v_ou from hr_operating_units hou where hou.organization_id = p_org_id; --获取物料类型 v_item_category:=trim(p_item_category); --获取物料从 v_inventory_item_f:=trim(p_inventory_item_f); --获取物料至 v_inventory_item_t:=trim(p_inventory_item_t); --获取物料呆滞天数 v_dead_days:=to_char(p_dead_days); --开始输出报表头信息 g_debug :='输出打印日期和用户输入条件'; output('<?xml version="1.0" encoding="UTF-8"?> <!-- Generated by Oracle Reports version 10.1.2.3.0 --> <CUXINVDEADSTOCK> <LIST_G_REPORT>'); output('<PRINT_DATE>' || v_print_date || '</PRINT_DATE>'); output('<OU>' || v_ou || '</OU>'); output('<ITEM_CATEGORY>' || v_item_category || '</ITEM_CATEGORY>'); output('<INVENTORY_ITEM_F>' || v_inventory_item_f || '</INVENTORY_ITEM_F>'); output('<INVENTORY_ITEM_T>' || v_inventory_item_t || '</INVENTORY_ITEM_T>'); output('<DEAD_DAYS>' || v_dead_days || '</DEAD_DAYS>'); --主体数据内循环开始 g_debug :='主体数据内循环开始'; for c1r in c1 loop output('<G_REPORT>'); output('<CATEGORY_CODE>' || c1r.item_category ||'.'|| c1r.item_sub_category || '</CATEGORY_CODE>'); output('<ITEM_CODE>' || c1r.segment1 || '</ITEM_CODE>'); output('<ITEM_DESCRIPTION>' || cux_common_pkg.Xml_Format(c1r.description) || '</ITEM_DESCRIPTION>'); output('<ITEM_UOM>' || c1r.primary_unit_of_measure || '</ITEM_UOM>'); output('<ITEM_ONHAND>' || c1r.Onhand_Quantity || '</ITEM_ONHAND>'); output('<LAST_TRANSACTION>' || to_char(c1r.last_transaction_date,'YYYY-MM-DD HH24:MI:SS') || '</LAST_TRANSACTION>'); output('<DEAD_STOCK_DAYS>' || c1r.Dead_Stock_Days || '</DEAD_STOCK_DAYS>'); output('<ITEM_COST>' || c1r.Item_Cost || '</ITEM_COST>'); output('<ONHAND_AMOUNT>' || c1r.onhand_amount || '</ONHAND_AMOUNT>'); output('</G_REPORT>'); end loop; output('</LIST_G_REPORT>'); output('</CUXINVDEADSTOCK>'); exception when others then g_error := SQLERRM; INSERT INTO session_log --记录异常信息到异常表 VALUES (SYSDATE, 'INVENTORY', 'CUX_INV_DEAD_STOCK_DETAIL_PKG', g_debug, g_error); COMMIT; outlog('出现错误'); end inv_dead_stock_detail_main; end CUX_INV_DEAD_STOCK_DETAIL_PKG; 这样变更后,在正式环境中运行的时为3分钟46秒,测试环境,从7小时变是20分钟。