Quantcast
Channel: Recent Questions - Stack Overflow
Viewing all articles
Browse latest Browse all 11601

Remake PL/SQL Function for better performance

$
0
0
  • Can this function be improved for faster loading?

I made this function for calculating quantities of products per customer after deduction of a certain amount of stock in the warehouses if it exists. This function goes in a View, which is in turn used to calculate material needs by another final query, which is displayed in a page in an APEX v19.2 application.

So the page normally took 15 - 20 secs to load and by adding the function in question as well as a couple of calculations in the View, those are the sum of the warehouses with subqueries and a division of the returned amount from the function (I will post the View's query as well), it now takes a minute give or take. The function:

create or replace FUNCTION fadjust_final_order_qnt(pProd NUMBER)  RETURN ADJUST_FINAL_ORDER_QNT_OBJ PIPELINED AS   TYPE cus_n_prods_rec IS RECORD   (      cus_id        number--,      --product_id    number   );   TYPE cus_n_prods_tbl IS TABLE OF cus_n_prods_rec;  lcus_n_prods_tbl cus_n_prods_tbl;  lwrh NUMBER := 0;BEGIN  SELECT NVL(SUM(CASE WHEN wrh_gr > 0 THEN wrh_gr ELSE 0 END),0) +             NVL(SUM(CASE WHEN wrh_bg > 0 THEN wrh_bg ELSE 0 END),0)    INTO lwrh                                                           --  get warehouses    FROM (      SELECT        aop.product_id as prod_id,        NVL((SELECT SUM(gr.balance) FROM MV_PROD_WH_GR gr, eba_products_mapping mg, eba_cust_products eg             WHERE gr.fitemgid = mg.gid AND mg.product_id = eg.id AND mg.origin = 'GR' AND eg.id = ecp.id), 0) wrh_gr,        NVL((SELECT SUM(bg.balance) FROM MV_PROD_WH_BG bg, eba_products_mapping mb, eba_cust_products eb             WHERE bg.fitemgid = mb.gid AND mb.product_id = eb.id AND mb.origin = 'BG' AND eb.id = ecp.id), 0) wrh_bg,        (SELECT epcv.descr FROM eba_prod_category_val epcv WHERE epcv.id = ecp.epc_1 AND epcv.epc_id = 1) Production      FROM APT_ORDERS_PRODUCTS aop        JOIN APT_ORDERS aor ON aor.id = aop.order_id        JOIN eba_cust_products ecp ON aop.product_id = ecp.id        JOIN eba_cust_customers ecc ON aor.cus_id = ecc.id      WHERE        ecc.status_id != 5 AND        --aor.status_id != 24 AND        aor.created_by NOT IN (4425, 239, 945, 1813, 598) AND        aor.status_id NOT IN (24, 41) AND        aor.invoice_number IS NULL AND        aor.created >= TO_DATE('01/01/2022', 'dd/mm/yyyy')    )    WHERE Production IS NOT NULL     AND prod_id = pProd     AND ROWNUM = 1;    select distinct        cus_id--,        --product_id    BULK COLLECT INTO lcus_n_prods_tbl                        -- For performance    from(      SELECT         (Select epcv.descr from eba_prod_category_val epcv where epcv.id= ecp.epc_1 and epcv.epc_id=1 ) Production,        aor.cus_id,        aop.product_id      FROM APT_ORDERS_PRODUCTS aop        JOIN APT_ORDERS aor ON aor.id = aop.order_id        JOIN eba_cust_products ecp ON aop.product_id = ecp.id        JOIN eba_cust_customers ecc ON aor.cus_id = ecc.id      WHERE        ecc.status_id != 5         --AND aor.status_id != 24         AND aor.created_by NOT IN (4425, 239, 945, 1813, 598)         AND aor.status_id NOT IN (24, 41)         AND aor.invoice_number IS NULL         AND aor.created >= TO_DATE('01/01/2022', 'dd/mm/yyyy')        -- AND (SELECT epcv.descr FROM eba_prod_category_val epcv WHERE epcv.id = ecp.epc_1 AND epcv.epc_id = 1) IS NOT NULL         )    where Production is not null    AND product_id = pProd;  FOR i IN 1 .. lcus_n_prods_tbl.COUNT LOOP    DECLARE      lamt NUMBER := 0;    BEGIN      FOR k IN (        SELECT SUM(quantity) qnt        FROM (          SELECT aop.quantity,            aop.product_id prod_id,            aor.cus_id,            (SELECT epcv.descr FROM eba_prod_category_val epcv WHERE epcv.id = ecp.epc_1 AND epcv.epc_id = 1) Production         FROM APT_ORDERS_PRODUCTS aop            JOIN APT_ORDERS aor ON aor.id = aop.order_id            JOIN eba_cust_products ecp ON aop.product_id = ecp.id            JOIN eba_cust_customers ecc ON aor.cus_id = ecc.id          WHERE            ecc.status_id != 5 AND            --aor.status_id != 24 AND            aor.created_by NOT IN (4425, 239, 945, 1813, 598) AND            aor.status_id NOT IN (24, 41) AND            aor.invoice_number IS NULL AND            aor.created >= TO_DATE('01/01/2022', 'dd/mm/yyyy')             --(SELECT epcv.descr FROM eba_prod_category_val epcv WHERE epcv.id = ecp.epc_1 AND epcv.epc_id = 1) IS NOT NULL AND        )        WHERE Production IS NOT NULL        and prod_id = pProd--lcus_n_prods_tbl(i).product_id        and cus_id = lcus_n_prods_tbl(i).cus_id      )       LOOP        lamt := lamt + k.qnt;      END LOOP;      FOR j IN (select det_id,                            cus_id,                            prod_id,                            order_id                        from(        SELECT aop.id det_id,          aor.cus_id,          aop.product_id prod_id,          aor.id order_id,          (SELECT epcv.descr FROM eba_prod_category_val epcv WHERE epcv.id = ecp.epc_1 AND epcv.epc_id = 1) Production        FROM APT_ORDERS_PRODUCTS aop          JOIN APT_ORDERS aor ON aor.id = aop.order_id          JOIN eba_cust_products ecp ON aop.product_id = ecp.id          JOIN eba_cust_customers ecc ON aor.cus_id = ecc.id        WHERE          ecc.status_id != 5 AND          --aor.status_id != 24 AND          aor.created_by NOT IN (4425, 239, 945, 1813, 598) AND          aor.status_id NOT IN (24, 41) AND          aor.invoice_number IS NULL AND          aor.created >= TO_DATE('01/01/2022', 'dd/mm/yyyy')          --(SELECT epcv.descr FROM eba_prod_category_val epcv WHERE epcv.id = ecp.epc_1 AND epcv.epc_id = 1) IS NOT NULL AND           )where Production is not null            and prod_id = pProd--lcus_n_prods_tbl(i).product_id            and cus_id = lcus_n_prods_tbl(i).cus_id      ) LOOP         if lwrh > 0 then            select decode(sign(lamt - lwrh),-1,0,lamt - lwrh),lwrh - lamt into lamt,lwrh from dual;            PIPE ROW (ADJUST_FINAL_ORDER_QNT_REC(lamt, pProd/*j.prod_id*/, j.cus_id, j.det_id));         else            PIPE ROW (ADJUST_FINAL_ORDER_QNT_REC(lamt, pProd/*j.prod_id*/, j.cus_id, j.det_id));         end if;      END LOOP;    END;  END LOOP;  RETURN;END;

The View query:

select     sum_qnt,     code,     prod_id,     description,     wrh_gr,     wrh_bg,      (select Amt from Table(fadjust_final_order_qnt(prod_id))where Prd = prod_id and Cus = cus_id and Id = det_id )/count(prod_id)over(partition by prod_id,cus_id) final_order_quantity,     cat_id,     cus_id,     order_idfrom (    select  sum(quantity) sum_qnt,            code ,            prod_id,            case when wrh_gr <= 0 then 0 when wrh_gr is null then 0 else wrh_gr end wrh_gr_v,            case when wrh_bg <= 0 then 0 else wrh_bg end wrh_bg_v ,            nvl(wrh_gr,0) wrh_gr,            nvl(wrh_bg,0) wrh_bg,            description,            cus_id,            order_id,            cat_id,            det_id    from (        SELECT  aop.id det_id,                aor.id order_id,                ecp.product_name code,                nvl(ecp.global_descr, ecp.description) description,                aop.quantity quantity,                (Select epcv.descr from eba_prod_category_val epcv where epcv.id= ecp.epc_1 and epcv.epc_id=1 ) Production ,                (select sum(gr.balance) from MV_PROD_WH_GR gr,  eba_products_mapping mg , eba_cust_products eg where gr.fitemgid = mg.gid and mg.product_id = eg.id and mg.origin = 'GR' and eg.id =ecp.id ) wrh_gr,                (select sum(bg.balance) from MV_PROD_WH_BG bg,  eba_products_mapping mb , eba_cust_products eb where bg.fitemgid = mb.gid and mb.product_id = eb.id and mb.origin = 'BG' and eb.id =ecp.id ) wrh_bg,                aop.product_id as prod_id,                aor.cus_id cus_id,                ecp.prod_cat_id cat_id        FROM  APT_ORDERS_PRODUCTS aop ,              APT_ORDERS aor,              eba_cust_products ecp,              eba_cust_customers ecc        WHERE AOR.ID = AOP.ORDER_ID          and aor.cus_id = ecc.id          and ecc.status_id != 5          and aop.product_id = ecp.id          and aor.status_id!=24          and aor.created_by not in (4425,239,945,1813,598)          and aor.status_id not in (24,41)          and aor.invoice_number is null          and aor.created >= to_date('01/01/2022','dd/mm/yyyy')        )where Production is not null        group by code,            wrh_gr,            wrh_bg,            description,            prod_id,            cat_id,             cus_id,             order_id,             det_id )

I managed to improve it by adding Bulk Collect Into and by reducing Select Into clauses as much as possible. I also created some more indexes for the columns used in the Where clause of the queries. Pagination didn't work in the Interactive Report in APEX page, although I didn't believe it would do anything I gave it a try.

With all the above I gained 5 - 10 seconds.


Viewing all articles
Browse latest Browse all 11601

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>