Home » SQL & PL/SQL » SQL & PL/SQL » can someone tell me why this sp takes so much time? (11g,toad 12.1)
can someone tell me why this sp takes so much time? [message #610041] Mon, 17 March 2014 03:18 Go to next message
ashwanth77
Messages: 95
Registered: April 2013
Location: India
Member
When executing the below stored procedure it takes 20 mins .The expected time is 2-3 mins. why this is happening? can someone tell me why this sp takes so much time?what can be done to make it run faster? Thanks a lot in advance.The logic of this procedure is ,it checks whether the order number is present in the table if not then inserts into that table

Procedure code



[EDITED by LF: applied [spoiler] tags to save everyone from too much scrolling]

[Updated on: Mon, 17 March 2014 06:12] by Moderator

Report message to a moderator

Re: can someone tell me why this sp takes so much time? [message #610044 is a reply to message #610041] Mon, 17 March 2014 03:32 Go to previous messageGo to next message
Michel Cadot
Messages: 68647
Registered: March 2007
Location: Nanterre, France, http://...
Senior Member
Account Moderator

Quote:
Thanks a lot in advance.The logic of this procedure is ,it checks whether the order number is present in the table if not then inserts into that table


Why not a single MERGE or INSERT?

Also read WHEN OTHERS.

Re: can someone tell me why this sp takes so much time? [message #610046 is a reply to message #610041] Mon, 17 March 2014 03:33 Go to previous messageGo to next message
John Watson
Messages: 8931
Registered: January 2010
Location: Global Village
Senior Member
It looks possible that the whole procedure has a number of fundamental flaws. In no particular order:

Your use of WHEN OTHERS is going to make de-bugging very difficult.
The row-by-row procedural processing of your data set is always going to perform worse than using SQL to operate on the complete set of rows in one operation.
The manner in which you run queries at various points is liable to give inconsistent results of any other sessions are connected while running this procedure.
The complete absence of comments in the code makes it hard to work out what you are trying to do.

All that having been said, you have placed many dbms_output calls in the code, but you have omitted to show the results. If you can show the output, with how many rows and which part is slow, perhaps someone can advise. You might want to consider using dbms_hprof or dbms_profiler to determine where the time is being spent.
Re: can someone tell me why this sp takes so much time? [message #610051 is a reply to message #610041] Mon, 17 March 2014 03:47 Go to previous messageGo to next message
javed.khan
Messages: 340
Registered: November 2006
Location: Banglore
Senior Member

How many rows?
Re: can someone tell me why this sp takes so much time? [message #610064 is a reply to message #610051] Mon, 17 March 2014 05:26 Go to previous messageGo to next message
ashwanth77
Messages: 95
Registered: April 2013
Location: India
Member
500+ rows ,now the time is reduced to 14 mins after removing when others clause,but the expected time is 2-3 mins
Re: can someone tell me why this sp takes so much time? [message #610067 is a reply to message #610064] Mon, 17 March 2014 05:34 Go to previous messageGo to next message
Michel Cadot
Messages: 68647
Registered: March 2007
Location: Nanterre, France, http://...
Senior Member
Account Moderator

Still remain the other points.

Re: can someone tell me why this sp takes so much time? [message #610081 is a reply to message #610067] Mon, 17 March 2014 08:05 Go to previous messageGo to next message
javed.khan
Messages: 340
Registered: November 2006
Location: Banglore
Senior Member

Quote:
expected time is 2-3 mins

How you know..? Can be less too unless you have one you have tested already in past before changing. By the way too much type casting i can see.
Re: can someone tell me why this sp takes so much time? [message #610087 is a reply to message #610067] Mon, 17 March 2014 08:40 Go to previous messageGo to next message
ashwanth77
Messages: 95
Registered: April 2013
Location: India
Member
The changes made to the existing code.now the time got reduced by 8 times.but thats not enough

BEGIN
         INSERT INTO frontroom.ordr
                     (ord_number, ds_ds_id, erlst_ship_dt, carrier,
                      vehicle_number, ord_dt, source_key, sf_sf_id,
                      cust_cust_id, ord_stat_ord_stat_id, le_le_id,
                      mkt_mkt_id, sc_sc_id, ctrl_dt, po_number,
                      expct_ship_date, bt_bt_id, order_process_dt,
                      storage_loc)
                      
                      VALUES(l_source_key, l_ds_ds_id, i.ship_date, l_carrier,
                   l_vehicle_number, i.ship_date, l_source_key, l_sf_sf_id,
                   l_cust_cust_id, l_ord_stat_ord_stat_id, l_le_le_id,
                   l_mkt_mkt_id, 0, i.ship_date, l_po_number, i.ship_date,
                   l_bt_bt_id, i.ship_date, l_storage_loc);
                    COMMIT;
                   
          /*  SELECT l_source_key, l_ds_ds_id, i.ship_date, l_carrier,
                   l_vehicle_number, i.ship_date, l_source_key, l_sf_sf_id,
                   l_cust_cust_id, l_ord_stat_ord_stat_id, l_le_le_id,
                   l_mkt_mkt_id, 0, i.ship_date, l_po_number, i.ship_date,
                   l_bt_bt_id, i.ship_date, l_storage_loc
              FROM DUAL
             WHERE NOT EXISTS (SELECT 1--ord_number
                                 FROM frontroom.ordr
                                WHERE ord_number = l_source_key);*/

      EXCEPTION
       WHEN DUP_VAL_ON_INDEX THEN
      l_error_msg := SQLERRM;
            sp_log_entry (SYSDATE,
                          'SP_LOAD_ORDER',
                          NULL,
                          l_error_msg,
                         'DUPLICATE RECORD FOUND FOR order_num_cos = ' || i.order_num_cos,
                          NULL
                         );
      
         WHEN OTHERS
         THEN
            l_error_msg := SQLERRM;
            sp_log_entry (SYSDATE,
                          'SP_LOAD_ORDER',
                          NULL,
                          l_error_msg,
                         'order_num_cos = ' || i.order_num_cos,
                          NULL
                         );
                         GOTO end_loop;
                         
                        
                         
                         
      END;
Re: can someone tell me why this sp takes so much time? [message #610088 is a reply to message #610087] Mon, 17 March 2014 08:54 Go to previous messageGo to next message
Michel Cadot
Messages: 68647
Registered: March 2007
Location: Nanterre, France, http://...
Senior Member
Account Moderator

Quote:
.now the time got reduced by 8 times.


This means how much?
Anyway, if this is just an INSERT VALUES it could not last more than a couple of 10ms.

Re: can someone tell me why this sp takes so much time? [message #610112 is a reply to message #610087] Mon, 17 March 2014 12:53 Go to previous messageGo to next message
John Watson
Messages: 8931
Registered: January 2010
Location: Global Village
Senior Member
You could post the results of the query, you know, with the timings.

I think your problem is now that you are inserting 500 rows in 500 statements. Row-by-row processing! SQL is a set oriented language, and you should use it accordingly. Do not read 500 rows into a cursor and insert them individually. Rather, insert all 500 in one statement:
INSERT INTO frontroom.ordr ... SELECT ... FROM stage_na_shipment;
If you are worried about duplicate keys, either use a MERGE as Michel suggested or use a LOG ERRORS INTO clause.
Re: can someone tell me why this sp takes so much time? [message #610137 is a reply to message #610112] Tue, 18 March 2014 01:49 Go to previous messageGo to next message
ashwanth77
Messages: 95
Registered: April 2013
Location: India
Member
Quote:
Row-by-row processing! SQL is a set oriented language. insert all 500 in one statement


INSERT INTO frontroom.ordr ... SELECT ... FROM stage_na_shipment;

after making the changes now the sp takes 4-5 mins to execute.the actual time taken should be 2-3 mins for 1000+rows
Re: can someone tell me why this sp takes so much time? [message #610139 is a reply to message #610137] Tue, 18 March 2014 02:11 Go to previous messageGo to next message
Michel Cadot
Messages: 68647
Registered: March 2007
Location: Nanterre, France, http://...
Senior Member
Account Moderator

Add APPEND and/or PARALLEL hint, if you can do it.
Buy faster disks and CPU.
Where does come this "2-3 mins"?

Re: can someone tell me why this sp takes so much time? [message #610145 is a reply to message #610137] Tue, 18 March 2014 02:33 Go to previous messageGo to next message
John Watson
Messages: 8931
Registered: January 2010
Location: Global Village
Senior Member
Can you show what is happening? You went to all the trouble of instrumenting the code, but refuse to show the results. You haven't provided the latest version of the code, either. Iy is difficult to tune something that is invisible Confused
Re: can someone tell me why this sp takes so much time? [message #610160 is a reply to message #610145] Tue, 18 March 2014 03:25 Go to previous messageGo to next message
ashwanth77
Messages: 95
Registered: April 2013
Location: India
Member
here is the code

output:

SQL> exec sp_load_order
Procedure started18-MAR-14 04.14.25.754121 AM
Inserted into order product table
Procedure ends18-MAR-14 04.18.41.774409 AM

PL/SQL procedure successfully completed.

Elapsed: 00:04:16.83
SQL> spool off


the disk is capable of running the sp faster


[EDITED by LF: applied [spoiler] tags]

[Updated on: Tue, 18 March 2014 15:34] by Moderator

Report message to a moderator

Re: can someone tell me why this sp takes so much time? [message #610162 is a reply to message #610160] Tue, 18 March 2014 03:58 Go to previous messageGo to next message
John Watson
Messages: 8931
Registered: January 2010
Location: Global Village
Senior Member
I do not understand. you said this
Quote:
INSERT INTO frontroom.ordr ... SELECT ... FROM stage_na_shipment;

after making the changes now the sp takes 4-5 mins to execute.the actual time taken should be 2-3 mins for 1000+rows
which suggests that you have followed my advice. But you haven't. You are doing row-by-row processing in loop. That is why your code is slow.
Re: can someone tell me why this sp takes so much time? [message #610163 is a reply to message #610162] Tue, 18 March 2014 04:10 Go to previous messageGo to next message
ashwanth77
Messages: 95
Registered: April 2013
Location: India
Member
how can i avoid row-by-row processing in loop?u mean to say using filters

[Updated on: Tue, 18 March 2014 04:12]

Report message to a moderator

Re: can someone tell me why this sp takes so much time? [message #610165 is a reply to message #610163] Tue, 18 March 2014 04:18 Go to previous messageGo to next message
cookiemonster
Messages: 13920
Registered: September 2008
Location: Rainy Manchester
Senior Member
He means rewrite the whole thing as two insert/select statements.

Write a single select statement that returns all the data that needs to be inserted into one of the tables then turn it into an insert select:
INSERT INTO ordr_product
(volume, revenue, source_key, ord_ord_id, prod_prod_id, local_currency)
SELECT <columns>
FROM <tables>
WHERE <where clause>


Get that working then do the same for the other table.
You need a fraction of the code you currently have.
Re: can someone tell me why this sp takes so much time? [message #610190 is a reply to message #610165] Tue, 18 March 2014 06:22 Go to previous messageGo to next message
ashwanth77
Messages: 95
Registered: April 2013
Location: India
Member
i have rewritten my query as

INSERT INTO frontroom.ordr
(ord_number, ds_ds_id, erlst_ship_dt, carrier,
vehicle_number, ord_dt, source_key, sf_sf_id,
cust_cust_id, ord_stat_ord_stat_id, le_le_id,
mkt_mkt_id, sc_sc_id, ctrl_dt, po_number,
expct_ship_date, bt_bt_id, order_process_dt,
storage_loc)

SELECT l_source_key, l_ds_ds_id, i.ship_date, l_carrier,
l_vehicle_number, i.ship_date, l_source_key, l_sf_sf_id,
l_cust_cust_id, l_ord_stat_ord_stat_id, l_le_le_id,
l_mkt_mkt_id, 0, i.ship_date, l_po_number, i.ship_date,
l_bt_bt_id, i.ship_date, l_storage_loc
FROM DUAL where l_source_key=i.order_num_cos;

INSERT INTO ordr_product
(volume, revenue, source_key, ord_ord_id, prod_prod_id,
local_currency)

SELECT i.ship_unit_code, 0, l_source_key_1, l_ord_ord_id,
l_prod_prod_id, i.currency
FROM DUAL where l_source_key=i.order_num_cos;

this didn't make any difference in time
Re: can someone tell me why this sp takes so much time? [message #610191 is a reply to message #610190] Tue, 18 March 2014 06:27 Go to previous messageGo to next message
cookiemonster
Messages: 13920
Registered: September 2008
Location: Rainy Manchester
Senior Member
Of course it doesn't.

The select in the insert/select needs to replace all the other selects in the procedure.
There should be no selects apart from the ones in the insert statements.
Re: can someone tell me why this sp takes so much time? [message #610194 is a reply to message #610190] Tue, 18 March 2014 06:38 Go to previous messageGo to next message
John Watson
Messages: 8931
Registered: January 2010
Location: Global Village
Senior Member
I'll have one more go. Look at this:
orclz>
orclz> create table t1(c1 number);

Table created.

orclz> insert into t1 select empno from emp;

14 rows created.

orclz>

That is using SQL: inserting a set of 14 rows with one statement.
SQL is a set oriented language, not a procedural language. Do NOT operate on rows individually.
Re: can someone tell me why this sp takes so much time? [message #610206 is a reply to message #610194] Tue, 18 March 2014 08:01 Go to previous messageGo to next message
ashwanth77
Messages: 95
Registered: April 2013
Location: India
Member
If i remove all the select statements ,how can i find the cust_id,prod_id,sf_id,bt_id ..for individual record ,which i have used inside the loop.den i should use a select statement in column list

[Updated on: Tue, 18 March 2014 08:08]

Report message to a moderator

Re: can someone tell me why this sp takes so much time? [message #610210 is a reply to message #610206] Tue, 18 March 2014 08:30 Go to previous messageGo to next message
cookiemonster
Messages: 13920
Registered: September 2008
Location: Rainy Manchester
Senior Member
By writing a single select statement that gets all the values needed.

So for starters you have these:
SELECT order_num_cos, ship_date, haulier_name, haulier_num,
                        po_number, stor_loc, ship_unit_code, ship_unit_code_8,
                        so_item, ship_from, del_point, currency, client, quantity
                   FROM stage_na_shipment
                   
.........
SELECT mkt_id  INTO l_mkt_mkt_id
               FROM market
              WHERE code =  DECODE (SUBSTR (l_client, 1, 4), 'US23', 'MM',
                                            'US99', 'AFFCO' )

They can be combined into
SELECT sns.order_num_cos, sns.ship_date, sns.haulier_name, sns.haulier_num,
       sns.po_number, sns.stor_loc, sns.ship_unit_code, sns.ship_unit_code_8,
       sns.so_item, sns.ship_from, sns.del_point, sns.currency, sns.client, sns.quantity,
       m.mkt_id
FROM stage_na_shipment sns, market m
WHERE m.code = DECODE (SUBSTR (TO_CHAR (sns..client), 1, 4), 'US23', 'MM',
                                            'US99', 'AFFCO' )


Now combine all the other selects into the above until you have one select that returns all the data that you need to insert, then make that select into an insert/select.
Re: can someone tell me why this sp takes so much time? [message #610214 is a reply to message #610210] Tue, 18 March 2014 09:04 Go to previous messageGo to next message
cookiemonster
Messages: 13920
Registered: September 2008
Location: Rainy Manchester
Senior Member
You were supplied with a full insert/select (untested admittedly) example several days ago on OTN. So I'm somewhat baffled as how you could fail to understand our repeated instructions to rewrite as an insert/select. Most of the hard work has already been done for you.
Re: can someone tell me why this sp takes so much time? [message #610480 is a reply to message #610041] Thu, 20 March 2014 09:31 Go to previous messageGo to next message
ashwanth77
Messages: 95
Registered: April 2013
Location: India
Member
This i wat i was trying


CREATE OR REPLACE PROCEDURE STAGING.sp_load_order_test
IS
  
 --  n_1                      NUMBER;
   l_error_msg              VARCHAR2 (500);
    l_ord_ord_id             ordr.ord_id%TYPE;
   l_ord_ord_id_1            ordr.ord_id%TYPE;
   start_time timestamp;
   end_time timestamp;
BEGIN
start_time:=systimestamp;
    DBMS_OUTPUT.put_line ('Procedure started' ||start_time);
    
   /*doing a bulk insert as row by row processing is going to take too much of time */

      BEGIN
         INSERT INTO frontroom.ordr
                     (ord_number, ds_ds_id, erlst_ship_dt, carrier,
                      vehicle_number, ord_dt, source_key, sf_sf_id,
                      cust_cust_id, ord_stat_ord_stat_id, le_le_id,
                      mkt_mkt_id, sc_sc_id, ctrl_dt, po_number,
                      expct_ship_date, bt_bt_id, order_process_dt,
                      storage_loc)
                   
                SELECT sns.order_num_cos, 1,sns.ship_date, sns.haulier_name, 
                 sns.haulier_num,sns.ship_date,sns.order_num_cos,sf.sf_id,c.cust_id,2,1,m.mkt_id,0,sns.ship_date,sns.po_number,sns.ship_date,bt.bt_id, sns.ship_date,sns.stor_loc   
FROM stage_na_shipment sns, market m,ship_from sf,customer c,bill_type bt
WHERE m.code = DECODE (SUBSTR (TO_CHAR (sns.client), 1, 4), 'US23', 'MM',
                                            'US99', 'AFFCO' ) and sf. source_key = sns.ship_from
                                            and  c.true_gcdb_source_key = TO_CHAR (sns.del_point) and bt.code='O'  ;
                   
       
               COMMIT;
             
               
               /*this works as all rows gets inserted to the table in a flash*/
         

      EXCEPTION
      WHEN DUP_VAL_ON_INDEX THEN
      l_error_msg := SQLERRM;
           sp_log_entry (SYSDATE,
                         'SP_LOAD_ORDER_TEST',
                         NULL,
                          l_error_msg,
                         'DUPLICATE RECORD FOUND ' ,
                         NULL
     );
      
         WHEN OTHERS
         THEN
            l_error_msg := SQLERRM;
            sp_log_entry (current_timestamp,
                          'SP_LOAD_ORDER_TEST',
                          NULL,
                          l_error_msg,
                         NULL,
                          NULL
                         );
                     --    GOTO end_loop;
                         
                        
                         
                         
      END;

   DBMS_OUTPUT.put_line ('Inserted into order table');
     

      
 /*how can i find the ord id for each and every ord number being inserted into ordr table*/
      
      SELECT ord_id
     INTO l_ord_ord_id
       FROM frontroom.ordr,stage_na_shipment sns
       WHERE ord_number = sns.order_num_cos;                  

DBMS_OUTPUT.put_line (l_ord_ord_id);


      BEGIN
         INSERT INTO ordr_product
                     (volume, revenue, source_key, ord_ord_id, prod_prod_id,
                      local_currency)
                     select  sns.ship_unit_code, 0, sns.order_num_cos || sns.so_item, l_ord_ord_id,
                   p.prod_prod_id, sns.currency from stage_na_shipment sns,product p where  p.secondary_source_key = LTRIM (sns.ship_unit_code_8, 0) ;
                   
               
      EXCEPTION
      WHEN DUP_VAL_ON_INDEX THEN
      l_error_msg := SQLERRM;
           sp_log_entry (SYSDATE,
                          'SP_LOAD_ORDER',
                        NULL,
                         l_error_msg,
                       'DUPLICATE RECORD FOUND ',
                        NULL);
         WHEN OTHERS
         THEN
            l_error_msg := SQLERRM;
            sp_log_entry (current_timestamp,
                          'SP_LOAD_ORDER_TEST',
                          NULL,
                          l_error_msg,
                         NULL,
                          NULL
                         );
                      --   GOTO end_loop;
      END;
    end loop;
      
  --     n_1 := n_1 + 1;
   --   if n_1 = 100 then
   --            COMMIT;
  --              n_1 :=  0;
  --    end if;

  --    <<end_loop>>
  --    null;
      
  end_time:=systimestamp;
    DBMS_OUTPUT.put_line ('Procedure ends' ||end_time);
   COMMIT;
   
EXCEPTION
   WHEN OTHERS
   THEN
      l_error_msg := SQLERRM;
      sp_log_entry (current_timestamp,'SP_LOAD_ORDER_TEST', NULL, l_error_msg, NULL, NULL);
END sp_load_order_test;
/

[Updated on: Thu, 20 March 2014 09:38]

Report message to a moderator

Re: can someone tell me why this sp takes so much time? [message #610481 is a reply to message #610480] Thu, 20 March 2014 09:36 Go to previous messageGo to next message
Michel Cadot
Messages: 68647
Registered: March 2007
Location: Nanterre, France, http://...
Senior Member
Account Moderator
WHEN OTHERS
         THEN
            l_error_msg := SQLERRM;
            sp_log_entry (current_timestamp,
                          'SP_LOAD_ORDER_TEST',
                          NULL,
                          l_error_msg,
                         NULL,
                          NULL
                         );
                      --   GOTO end_loop;

NO! you do not go to end loop, you continue the block and the loop.
The correct way to do it is to add a RAISE statement and to handle it properly in outer block.

Re: can someone tell me why this sp takes so much time? [message #610485 is a reply to message #610481] Thu, 20 March 2014 09:59 Go to previous messageGo to next message
cookiemonster
Messages: 13920
Registered: September 2008
Location: Rainy Manchester
Senior Member
Is there a question there?
Re: can someone tell me why this sp takes so much time? [message #610488 is a reply to message #610485] Thu, 20 March 2014 11:00 Go to previous messageGo to next message
ashwanth77
Messages: 95
Registered: April 2013
Location: India
Member
how to find the bt_id using this condn

IF i.quantity >= 0
         THEN
            l_code := 'O';
         ELSE
            l_code := 'C';
         END IF;

         SELECT bt_id  INTO l_bt_bt_id  FROM bill_type
                    WHERE code = l_code
                     AND ds_ds_id = 1;



how can i append bt_id to my existing query


INSERT INTO frontroom.ordr
                     (ord_number, ds_ds_id, erlst_ship_dt, carrier,
                      vehicle_number, ord_dt, source_key, sf_sf_id,
                      cust_cust_id, ord_stat_ord_stat_id, le_le_id,
                      mkt_mkt_id, sc_sc_id, ctrl_dt, po_number,
                      expct_ship_date, bt_bt_id, order_process_dt,
                      storage_loc)
                      
                      SELECT sns.order_num_cos,1,sns.ship_date, sns.haulier_name, sns.haulier_num,sns.ship_date,sns.order_num_cos,sf.sf_id ,c.cust_id,2,1,m.mkt_id,0,sns.ship_date,sns.po_number,sns.ship_date,bt.bt_id,sns.ship_date,sns.stor_loc 
FROM stage_na_shipment sns, market m,ship_from sf ,customer c,bill_type bt WHERE m.code = DECODE (SUBSTR (TO_CHAR (sns.client), 1, 4), 'US23', 'MM',
                                            'US99', 'AFFCO' ) and sf. source_key = sns.ship_from and c.true_gcdb_source_key = TO_CHAR (sns.del_point);


[Updated on: Thu, 20 March 2014 11:01]

Report message to a moderator

Re: can someone tell me why this sp takes so much time? [message #610496 is a reply to message #610488] Thu, 20 March 2014 11:48 Go to previous message
cookiemonster
Messages: 13920
Registered: September 2008
Location: Rainy Manchester
Senior Member
Use a case statement to get the correct value of code.
Previous Topic: Issue in inserting table data through DB Link
Next Topic: Insert user_id if it doesn't already exist.
Goto Forum:
  


Current Time: Fri Apr 26 21:31:10 CDT 2024