Re: Stored Procedure Performance Problem --- Please Help

2001-09-02 Thread Jared Still

On Friday 31 August 2001 13:40, Stephane Faroult wrote:
> > Procedure:
> >
> > CREATE OR REPLACE PROCEDURE transform_prc IS
> >   CURSOR cur_main
> >   IS
> >   SELECT distinct idserver,
> >  to_char(dtreadingtime, 'DD-MON- HH24:MI') dttime
> > FROM tblcounter_reading a
> >WHERE ysntransformflag IS NULL
> >  AND to_char(a.dtreadingtime, 'DAY') NOT IN ('SUNDAY   ',
> > 'SATURDAY ');
>
> All right, mandatory table scan (functions make index usage impossible
> unless, as somebody suggested, you create an index-based index). In your
> case, I would not advise it since I guess that the bulk of your activity
> occurs from Monday to Friday inclusive, so you are going to exclude with
> the date criterion a ridiculously small fraction of your data - you are
> better off scanning. Concerning the flag, you may be aware that NULL
> value are often not stored at all, and are therefore not indexed. If the
> number of rows you expect to fetch with this restriction is small (i.e.
> the flag is not null in say 95% of cases) I suggest you make the column
> NOT NULL and set a default (unused) value, say '#' - which will make you
> able to index the column. If few rows contain this value and if it is
> indexed, WHERE YWNTRANSFORMFLAG = '#' will fly.

Since this cursor is the main loop, I don't see a problem with the full
table scan, unless the where clause actually limits the return set to
a small percentage of the total.  In any case, it doesn't take 20 hours
to read 13 million rows.  It's not *that* big.

>
>   I have trouble understanding your logic. Why the PL/SQL table?
> Wouldn't it be possible to do a join or whatever to retrieve the column
> name you want? Why do you want to scan the array? If Oracle can do it
> for you, do not hesitate, it may do it more efficiently.
>

I'll agree to that, for sure.  I read this code for a few minutes and 
decided that was enough.  It appears very convoluted to me.  What are you
really trying to accomplish here?

And as others have said, get rid of the dynamic SQL.  Or at least
use bind variables.

Jared

-- 
Please see the official ORACLE-L FAQ: http://www.orafaq.com
-- 
Author: Jared Still
  INET: [EMAIL PROTECTED]

Fat City Network Services-- (858) 538-5051  FAX: (858) 538-5051
San Diego, California-- Public Internet access / Mailing Lists

To REMOVE yourself from this mailing list, send an E-Mail message
to: [EMAIL PROTECTED] (note EXACT spelling of 'ListGuru') and in
the message BODY, include a line containing: UNSUB ORACLE-L
(or the name of mailing list you want to be removed from).  You may
also send the HELP command for other information (like subscribing).



Re: Stored Procedure Performance Problem --- Please Help

2001-08-31 Thread Stephane Faroult

Viral,

  There has been a few sensible advices but no global critic, so I think
that I can have a stab at it.

> Viral Amin wrote:
> 
> Hi All,
> 
> Hardware : Dell server - 256MB RAM, 13GB Hard Disk, Single CPU
> Software : Oracle 8.1.7 (Non-parallel server option)
> OS : Windows NT 4.0 SP6
> 
> BackGround: Following is the table structure and record count
> 
> desc tblcounter_reading
>  Name  Null?Type
>  - 
> 
>  IDNOT NULL NUMBER   --
> Primary Key
>  IDSERVER  NOT NULL NUMBER
>  IDCOUNTER NOT NULL NUMBER
>  DTREADINGTIME NOT NULL DATE
>  NUMREADINGVALUENUMBER(38,20)
>  YSNTRANSFORMFLAG   VARCHAR2(1)
> 
> SQL> select count(*) from tblcounter_reading;
> 
> 
> COUNT(*)
> 
> --
> 
>   13283499
> 
> Indexes on table TBLREPORTCOUNTER_READING
> 
> 1) Index on (id) PRIMARY KEY
> 2) Index on (id, dtreadingtime)

Index 2 could have some interest if, and only if, your queries could
be answered by looking at those two columns only (you would only have to
look at the index). This is not the case, since you have conditions on
other columns which force you to fetch the table row anyway. Believe me,
you can drop it. If you really feel sentimentally attached to it, at
least rebuild it in reverse order (dtreadingtime, id), otherwise it's
totally useless.
 
> Problem Description:
> 
> Following is the procedure which reads the above table and insert rows
> in the another table .
> This procedure execution takes very long time -- like 2-3 min for
> inserting one row in the other table. We need ways to  optimize this
> in the best possible manner so that the executiuon time is reduced.
> 
> Total time of execution - NOT KNOWN, could be ridiculously high like
> 20hrs or so.
> 
> Please help...In a very desparate situation.
> 
> Procedure:
> 
> CREATE OR REPLACE PROCEDURE transform_prc IS
>   CURSOR cur_main
>   IS
>   SELECT distinct idserver,
>  to_char(dtreadingtime, 'DD-MON- HH24:MI') dttime
> FROM tblcounter_reading a
>WHERE ysntransformflag IS NULL
>  AND to_char(a.dtreadingtime, 'DAY') NOT IN ('SUNDAY   ',
> 'SATURDAY ');

All right, mandatory table scan (functions make index usage impossible
unless, as somebody suggested, you create an index-based index). In your
case, I would not advise it since I guess that the bulk of your activity
occurs from Monday to Friday inclusive, so you are going to exclude with
the date criterion a ridiculously small fraction of your data - you are
better off scanning. Concerning the flag, you may be aware that NULL
value are often not stored at all, and are therefore not indexed. If the
number of rows you expect to fetch with this restriction is small (i.e.
the flag is not null in say 95% of cases) I suggest you make the column
NOT NULL and set a default (unused) value, say '#' - which will make you
able to index the column. If few rows contain this value and if it is
indexed, WHERE YWNTRANSFORMFLAG = '#' will fly.

> 
>   CURSOR cur_trans_main(pi_idserver IN NUMBER, pi_dtreadingtime IN
> DATE) IS
>   SELECT numreadingvalue, idcounter
> FROM tblcounter_reading
>WHERE idserver   = pi_idserver
>  AND dtreadingtime  = pi_dtreadingtime
>  FOR UPDATE OF ysntransformflag ;
>
>   CURSOR cur_tblcounter
> IS
>   SELECT   id, strrptcolname
> FROM   tblcounter
>WHERE   nvl(ysnrptflag, 'X') = 'Y';
> 
>   v_strrptcolname   TBLCOUNTER.STRRPTCOLNAME%TYPE;
>   v_collist   LONG   := Null;  -- Variable to store column list
> generated form TBLCOUNTER_READING table
>   v_valuelist LONG   := Null;  -- Variable to store value list
> generated form TBLCOUNTER_READING table
>   v_sql_stmt  LONG   := Null;  -- Variable to store Dynamic DML
>   v_alter_sess_stmt  VARCHAR2(1000)   := 'ALTER SESSION SET
> NLS_DATE_FORMAT = ' ||  || 'DD-MON- HH24:MI' ||  ;
> 
>   v_rowcnt Number := 1;
>   v_prev_srv TBLCOUNTER_READING.IDSERVER%TYPE;
> 
> -
> 
> -- Declare plsql table to store counter information from TBLCOUNTER
> table
> -
> 
>   TYPE tblcounter_TabType  IS TABLE OF tblcounter%ROWTYPE INDEX BY
> BINARY_INTEGER;
>   tblcnt tblcounter_TabType;
>

  I have trouble understanding your logic. Why the PL/SQL table?
Wouldn't it be possible to do a join or whatever to retrieve the column
name you want? Why do you want to scan the array? If Oracle can do it
for you, do not hesitate, it may do it more efficiently.

Nothing outrageously shocking in the rest of the code, but : 
1) as somebody remarked, parsing dynamically hard-coded statements
kills. I don't know your data, but if the (f

RE: Stored Procedure Performance Problem --- Please Help

2001-08-31 Thread Jamadagni, Rajendra

Another important thing  your insert statement should be rewritten to
use bind variables  i.e. EXECYTE IMMEDIATE  USING clause. This will
help reduce parsing as well.

HTH
Raj
__ 
Rajendra Jamadagni  MIS, ESPN Inc. 
Rajendra dot Jamadagni at ESPN dot com 
Any opinion expressed here is personal and doesn't reflect that of ESPN Inc.

QOTD: Any clod can have facts, but having an opinion is an art ! 

*1

This e-mail message is confidential, intended only for the named recipient(s) above 
and may contain information that is privileged, attorney work product or exempt from 
disclosure under applicable law. If you have received this message in error, or are 
not the named recipient(s), please immediately notify corporate MIS at (860) 766-2000 
and delete this e-mail message from your computer, Thank you.

*1

-- 
Please see the official ORACLE-L FAQ: http://www.orafaq.com
-- 
Author: Jamadagni, Rajendra
  INET: [EMAIL PROTECTED]

Fat City Network Services-- (858) 538-5051  FAX: (858) 538-5051
San Diego, California-- Public Internet access / Mailing Lists

To REMOVE yourself from this mailing list, send an E-Mail message
to: [EMAIL PROTECTED] (note EXACT spelling of 'ListGuru') and in
the message BODY, include a line containing: UNSUB ORACLE-L
(or the name of mailing list you want to be removed from).  You may
also send the HELP command for other information (like subscribing).



RE: Stored Procedure Performance Problem --- Please Help

2001-08-31 Thread Jack C. Applewhite
Title: Stored Procedure Performance Problem --- Please Help



Viral,
 
Are 
you saying your entire database is on one 13GB drive?  If so, it's no 
wonder this operation takes a very long time - you're I/O bound in a big 
way!  The inserts and updates of tables and indexes, not to mention disk 
sorts in the Temp segment, as well as rollback, redo, etc. are thrashing the 
heck out of that drive!
 
If you 
have multiple 13GB drives, then you need to tell us more about table, index and 
tablespace distribution.
 
Jack
Jack C. 
ApplewhiteDatabase Administrator/DeveloperOCP Oracle8 DBAiNetProfit, 
Inc.Austin, 
Texaswww.iNetProfit.com[EMAIL PROTECTED](512)327-9068

  -Original Message-From: [EMAIL PROTECTED] 
  [mailto:[EMAIL PROTECTED]]On Behalf Of Viral AminSent: 
  Friday, August 31, 2001 9:00 AMTo: Multiple recipients of list 
  ORACLE-LSubject: Stored Procedure Performance Problem --- Please 
  Help
  Hi All, 
  Hardware : Dell server - 256MB RAM, 13GB Hard Disk, 
  Single CPU Software : Oracle 8.1.7 
  (Non-parallel server option) OS : Windows 
  NT 4.0 SP6 
  BackGround: Following is the table structure and 
  record count 
   ... 
  Regards 
  Viral Amin 


RE: Stored Procedure Performance Problem --- Please Help

2001-08-31 Thread Deshpande, Kirti

Viral,
Have you tried to run this with tracing turned on? The trace file can show
you areas of concern. 

Also, you may want to look into using DBMS_PROFILER package to find
performance bottlenecks in your PL/SQL procedures. Read more about it in the
Oracle8i Supplied PL/SQL Packages Reference Guide. 

Regards,

- Kirti Deshpande 
  Verizon Information Services
   http://www.superpages.com

> -Original Message-
> From: Viral Amin [SMTP:[EMAIL PROTECTED]]
> Sent: Friday, August 31, 2001 9:00 AM
> To:   Multiple recipients of list ORACLE-L
> Subject:  Stored Procedure Performance Problem --- Please Help
> 
> Hi All, 
> 
> Hardware : Dell server - 256MB RAM, 13GB Hard Disk, Single CPU 
> Software : Oracle 8.1.7 (Non-parallel server option) 
> OS : Windows NT 4.0 SP6 
> 
> BackGround: Following is the table structure and record count 
> 
> desc tblcounter_reading 
>  Name  Null?Type 
>  - 
>  
>  IDNOT NULL NUMBER   -- Primary
> Key 
>  IDSERVER  NOT NULL NUMBER   
>  IDCOUNTER NOT NULL NUMBER 
>  DTREADINGTIME NOT NULL DATE 
>  NUMREADINGVALUENUMBER(38,20) 
>  YSNTRANSFORMFLAG   VARCHAR2(1) 
> 
> SQL> select count(*) from tblcounter_reading; 
> 
>   COUNT(*)
> 
> --
> 
>   13283499   
> 
> Indexes on table TBLREPORTCOUNTER_READING 
> 
> 1) Index on (id) PRIMARY KEY 
> 2) Index on (id, dtreadingtime) 
> 
> Problem Description: 
> 
> Following is the procedure which reads the above table and insert rows in
> the another table . 
> This procedure execution takes very long time -- like 2-3 min for
> inserting one row in the other table. We need ways to  optimize this in
> the best possible manner so that the executiuon time is reduced. 
> 
> Total time of execution - NOT KNOWN, could be ridiculously high like 20hrs
> or so. 
> 
> Please help...In a very desparate situation. 
> 
> 
> Procedure: 
> 
> CREATE OR REPLACE PROCEDURE transform_prc IS 
>   CURSOR cur_main 
>   IS 
>   SELECT distinct idserver, 
>  to_char(dtreadingtime, 'DD-MON- HH24:MI') dttime 
> FROM tblcounter_reading a 
>WHERE ysntransformflag IS NULL 
>  AND to_char(a.dtreadingtime, 'DAY') NOT IN ('SUNDAY   ', 'SATURDAY
> '); 
> 
>   CURSOR cur_trans_main(pi_idserver IN NUMBER, pi_dtreadingtime IN DATE)
> IS 
>   SELECT numreadingvalue, idcounter 
> FROM tblcounter_reading 
>WHERE idserver   = pi_idserver 
>  AND dtreadingtime  = pi_dtreadingtime 
>  FOR UPDATE OF ysntransformflag ; 
> 
>   CURSOR cur_tblcounter 
> IS 
>   SELECT   id, strrptcolname 
> FROM   tblcounter 
>WHERE   nvl(ysnrptflag, 'X') = 'Y'; 
> 
>   v_strrptcolname   TBLCOUNTER.STRRPTCOLNAME%TYPE; 
>   v_collist   LONG   := Null;  -- Variable to store column list generated
> form TBLCOUNTER_READING table 
>   v_valuelist LONG   := Null;  -- Variable to store value list  generated
> form TBLCOUNTER_READING table 
>   v_sql_stmt  LONG   := Null;  -- Variable to store Dynamic DML 
>   v_alter_sess_stmt  VARCHAR2(1000)   := 'ALTER SESSION SET
> NLS_DATE_FORMAT = ' ||  || 'DD-MON- HH24:MI' ||  ;
> 
>   v_rowcnt Number := 1; 
>   v_prev_srv TBLCOUNTER_READING.IDSERVER%TYPE; 
> 
> --
> --- 
> -- Declare plsql table to store counter information from TBLCOUNTER table 
> --
> --- 
> 
>   TYPE tblcounter_TabType  IS TABLE OF tblcounter%ROWTYPE INDEX BY
> BINARY_INTEGER; 
>   tblcnt tblcounter_TabType; 
> 
> --
> --- 
> -- Function to return the coulumn name for the counter flagged 'Y' in
> TBLCOUNTER table 
> --
> --- 
>   FUNCTION get_col_name(pi_idcounter IN Number) RETURN VARCHAR2 
> IS 
>   BEGIN 
> FOR counter IN 1..v_rowcnt LOOP 
>   IF tblcnt(counter).id = pi_idcounter THEN 
> RETURN tblcnt(counter).strrptcolname; 
> EXIT; 
>   END IF; 
> END LOOP; 
> RETURN 'XXX'; 
>   END; 
> 
> BEGIN 
> --
> --- 
> -- Set the date format for the user session 
> --
> --- 
>   EXECUTE IMMEDIATE v_alter_sess_stmt;  
> 
> --
> --- 
> -- Populate the plsql table with values from tblcounter table 
> --
> --- 
>   FOR tblcounter_rec IN cur_tblcounter LOOP 
> tblcnt(v_rowcnt).id := tblcounter_rec.id; 
>

RE: Stored Procedure Performance Problem --- Please Help

2001-08-31 Thread Jamadagni, Rajendra

Without TKPROF output it is difficult to pinpoint exact statement which is
causing all the problems. 

BUT wait .. you can optimize few things  

* You mention you are on 817, make use of BULK BINDING for handling all the
inserts, this will help speedup the process.

* If you create a Function based index for to_char(a.dtreadingtime, 'DY')
you can change the where clause to 
"where to_char(a.dtreadingtime, 'DY')  NOT IN ('SAT','SUN')" all while
using the index. By using DAY, and by specifying 'SUNDAY  ' the compiler may
be doing more work

* Looks like tblcounter.id will be unique ... in which case make use of
intelligent keys for pl/sql table you are using. Instead of inserting rows
starting at location 1 onwards ... insert a row where the index value is
tbcounter.id. This way, you won't need the inline function GET_COL_NAME
because you can replace the function calls as 
"v_strrptcolname := tblcnt(cur_trans_rec.idcounter).strrptcolname;" there by
removing the in-line function and repeated scans on the pl/sql table.

* For all your insert statements use bulk binds ... thae means you save the
data to be inserted in pl/sql tables and then in one statement you insert
all rows.

HTH
Raj
__
Rajendra Jamadagni  MIS, ESPN Inc.
Rajendra dot Jamadagni at ESPN dot com
Any opinion expressed here is personal and doesn't reflect that of ESPN Inc.

QOTD: Any clod can have facts, but having an opinion is an art !

*1

This e-mail message is confidential, intended only for the named recipient(s) above 
and may contain information that is privileged, attorney work product or exempt from 
disclosure under applicable law. If you have received this message in error, or are 
not the named recipient(s), please immediately notify corporate MIS at (860) 766-2000 
and delete this e-mail message from your computer, Thank you.

*1

-- 
Please see the official ORACLE-L FAQ: http://www.orafaq.com
-- 
Author: Jamadagni, Rajendra
  INET: [EMAIL PROTECTED]

Fat City Network Services-- (858) 538-5051  FAX: (858) 538-5051
San Diego, California-- Public Internet access / Mailing Lists

To REMOVE yourself from this mailing list, send an E-Mail message
to: [EMAIL PROTECTED] (note EXACT spelling of 'ListGuru') and in
the message BODY, include a line containing: UNSUB ORACLE-L
(or the name of mailing list you want to be removed from).  You may
also send the HELP command for other information (like subscribing).



RE: Stored Procedure Performance Problem --- Please Help

2001-08-31 Thread Koivu, Lisa
Title: RE: Stored Procedure Performance Problem --- Please Help





Where's your tkprof output? First step always is to trace.


-Original Message-
From:   Viral Amin [SMTP:[EMAIL PROTECTED]]
Sent:   Friday, August 31, 2001 10:00 AM
To: Multiple recipients of list ORACLE-L
Subject:    Stored Procedure Performance Problem --- Please Help


Hi All, 


Hardware : Dell server - 256MB RAM, 13GB Hard Disk, Single CPU
Software : Oracle 8.1.7 (Non-parallel server option)
OS : Windows NT 4.0 SP6 


BackGround: Following is the table structure and record count 


desc tblcounter_reading
 Name  Null?    Type
 -  
 ID    NOT NULL NUMBER   -- Primary Key
 IDSERVER  NOT NULL NUMBER  
 IDCOUNTER NOT NULL NUMBER
 DTREADINGTIME NOT NULL DATE
 NUMREADINGVALUE    NUMBER(38,20)
 YSNTRANSFORMFLAG   VARCHAR2(1) 


SQL> select count(*) from tblcounter_reading; 


  COUNT(*) 
-- 
  13283499   


Indexes on table TBLREPORTCOUNTER_READING 


1) Index on (id) PRIMARY KEY
2) Index on (id, dtreadingtime) 


Problem Description: 


Following is the procedure which reads the above table and insert rows in the another table .
This procedure execution takes very long time -- like 2-3 min for inserting one row in the other table. We need ways to  optimize this in the best possible manner so that the executiuon time is reduced. 

Total time of execution - NOT KNOWN, could be ridiculously high like 20hrs or so. 


Please help...In a very desparate situation. 



Procedure: 


CREATE OR REPLACE PROCEDURE transform_prc IS
  CURSOR cur_main
  IS
  SELECT distinct idserver,
 to_char(dtreadingtime, 'DD-MON- HH24:MI') dttime
    FROM tblcounter_reading a
   WHERE ysntransformflag IS NULL
 AND to_char(a.dtreadingtime, 'DAY') NOT IN ('SUNDAY   ', 'SATURDAY '); 


  CURSOR cur_trans_main(pi_idserver IN NUMBER, pi_dtreadingtime IN DATE) IS
  SELECT numreadingvalue, idcounter
    FROM tblcounter_reading
   WHERE idserver   = pi_idserver
 AND dtreadingtime  = pi_dtreadingtime
 FOR UPDATE OF ysntransformflag ; 


  CURSOR cur_tblcounter
    IS
  SELECT   id, strrptcolname
    FROM   tblcounter
   WHERE   nvl(ysnrptflag, 'X') = 'Y'; 


  v_strrptcolname   TBLCOUNTER.STRRPTCOLNAME%TYPE;
  v_collist   LONG   := Null;  -- Variable to store column list generated form TBLCOUNTER_READING table
  v_valuelist LONG   := Null;  -- Variable to store value list  generated form TBLCOUNTER_READING table
  v_sql_stmt  LONG   := Null;  -- Variable to store Dynamic DML
  v_alter_sess_stmt  VARCHAR2(1000)   := 'ALTER SESSION SET NLS_DATE_FORMAT = ' || '''' || 'DD-MON- HH24:MI' || '''' ;

  v_rowcnt Number := 1;
  v_prev_srv TBLCOUNTER_READING.IDSERVER%TYPE; 


-
-- Declare plsql table to store counter information from TBLCOUNTER table
- 


  TYPE tblcounter_TabType  IS TABLE OF tblcounter%ROWTYPE INDEX BY BINARY_INTEGER;
  tblcnt tblcounter_TabType; 


-
-- Function to return the coulumn name for the counter flagged 'Y' in TBLCOUNTER table
-
  FUNCTION get_col_name(pi_idcounter IN Number) RETURN VARCHAR2
    IS
  BEGIN
    FOR counter IN 1..v_rowcnt LOOP
  IF tblcnt(counter).id = pi_idcounter THEN
    RETURN tblcnt(counter).strrptcolname;
    EXIT;
  END IF;
    END LOOP;
    RETURN 'XXX';
  END; 


BEGIN
-
-- Set the date format for the user session
-
  EXECUTE IMMEDIATE v_alter_sess_stmt;  


-
-- Populate the plsql table with values from tblcounter table
-
  FOR tblcounter_rec IN cur_tblcounter LOOP
    tblcnt(v_rowcnt).id := tblcounter_rec.id;
    tblcnt(v_rowcnt).strrptcolname := tblcounter_rec.strrptcolname;
    v_rowcnt := v_rowcnt + 1;
  END LOOP;
 
-
-- Start transformation process for each server id in the cursor