MVSFORUMS.com Forum Index MVSFORUMS.com
A Community of and for MVS Professionals
 
 FAQFAQ   SearchSearch   Quick Manuals   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

DB2 Tuning required

 
Post new topic   Reply to topic   printer-friendly view    MVSFORUMS.com Forum Index -> Database
View previous topic :: View next topic  
Author Message
suresh_d
Beginner


Joined: 20 Sep 2006
Posts: 33
Topics: 9

PostPosted: Tue Sep 22, 2009 1:34 am    Post subject: DB2 Tuning required Reply with quote

Hi,

I need help in fine tuning the below cursors in my program which is taking very much time. I have no idea how to do a query optimisation.
Code:

DECLARE KUND1 CURSOR FOR                     
    SELECT DISTINCT A.PONR                   
          ,A.KUNDNR                           
          ,HUSHALLID                         
          ,A.BOLAGKOD                         
          ,YEAR(CURRENT DATE - FODELSEDATE)   
          ,MONTH(CURRENT DATE - FODELSEDATE) 
          ,DAVILLA                           
          ,CI_BRF                             
          ,A.LKFKOD                           
          ,A.LANSKOD                         
          ,A.KOMMUNKOD                       
          ,A.FORSAMLINGKOD                   
          ,SUBSTR(EMAILADRESS,1,50)           
          ,A.POSTNR                           
          ,PKISTATUS                         
          ,A.CUSTOMERVALUE                   
    FROM   TPY001KUND A                       
    WHERE EXISTS                             
         (SELECT 1 FROM TPY122FORSV B         
          WHERE A.PONR     = B.PONR           
          AND A.BOLAGKOD = B.BOLAGKOD         
          AND B.BRANSCHGRP IN                 
          ('CIVIL','MOTOR','OLFA','GRUPP'))   
      AND A.BOLAGKOD IN ('TH','AF')           
      AND A.PONR <> 0                         
      AND FODELSEDATE <> ' '                 
           AND A.REGTILLF IN                       
              (SELECT MAX(REGTILLF)               
               FROM TPY001KUND C                   
               WHERE C.PONR     = A.PONR           
                 AND C.BOLAGKOD = A.BOLAGKOD       
                 AND C.BOLAGKOD IN ('TH','AF'))   
         ORDER BY A.PONR                           
         WITH UR                                   
 END-EXEC.                                         
                                                   
 EXEC SQL                                         
     DECLARE MOTOR1 CURSOR FOR                     
         SELECT C.PONR                             
               ,A.FNR                             
               ,A.GRPNR                           
               ,A.OBJEKTNR                         
               ,A.REGTILLF                         
               ,A.KUNDNR                           
               ,FORDKLKOD                         
               ,DAYS(CURRENT DATE) - DAYS(BEGDATE)
               ,CI_BEHTYP2                         
               ,DAYS(CURRENT DATE) -               
                DAYS(VALUE(ANNUDATE,CURRENT DATE))
               ,FROMDATE                           
               ,TILLDATE                           
               ,CI_HFFMAN                         
               ,UBEGDATE                           
               ,A.BOLAGKOD                         
          FROM  TPY005MOTOR A                     
              ,TPY122FORSV C                     
         WHERE A.FNR      = C.FNR               
           AND A.GRPNR    = C.GRPNR             
           AND A.OBJEKTNR = C.OBJEKTNR           
           AND A.REGTILLF = C.REGTILLF           
           AND A.BOLAGKOD = C.BOLAGKOD           
           AND C.PONR      <> 0                 
         ORDER BY C.PONR                         
         WITH UR                                 
END-EXEC.                                       
                                                 
EXEC SQL                                         
    DECLARE CIVIL1 CURSOR FOR                   
        SELECT C.PONR                           
              ,A.FNR                             
              ,A.REGTILLF                       
              ,A.KUNDNR                         
              ,A.GRPNR                           
              ,A.OBJEKTNR                       
              ,CI_BEHTYP2                       
              ,DAYS(CURRENT DATE) - DAYS(BEGDATE)
              ,DAYS(CURRENT DATE) -             
               DAYS(VALUE(ANNUDATE,CURRENT DATE))
              ,BRANSCH                           
              ,FROMDATE                         
              ,TILLDATE                         
              ,FFORM                             
              ,UBEGDATE                                                               
              ,A.BOLAGKOD             
              ,CI_MEDFDAT1           
              ,CI_MEDFDAT2           
              ,CI_MEDFDAT3           
              ,CI_MEDFDAT4           
              ,CI_MEDFDAT5           
              ,CI_OLDAT1             
              ,CI_OLDAT2             
              ,CI_OLDAT3             
              ,CI_OLDAT4             
              ,CI_OLDAT5             
        FROM   TPY004CIVIL A         
              ,TPY122FORSV C         
        WHERE C.FNR      = A.FNR     
          AND C.GRPNR    = A.GRPNR   
          AND C.OBJEKTNR = A.OBJEKTNR
          AND C.REGTILLF = A.REGTILLF
          AND C.BOLAGKOD = A.BOLAGKOD
          AND C.PONR      <> 0       
        ORDER BY C.PONR               
        WITH UR                       
END-EXEC.                             
                                     
EXEC SQL                             
    DECLARE LMV1 CURSOR FOR           
        SELECT PNR                   
              ,LMVBOSTADSRATT         
              ,LMVTYPKOD             
        FROM   TPR010LMV             
                                            LINE 0
         ORDER BY PNR                             
         WITH UR                                 
 END-EXEC.                                       
                                                 
 EXEC SQL                                         
     DECLARE MEDLEMS1 CURSOR FOR                 
         SELECT DISTINCT A.PONR                   
               ,MEDLEMSKOD                       
               ,A.BOLAGKOD                       
         FROM   TPY122FORSV A                     
         WHERE CI_BEHTYP2 <> 'AN'                 
           AND CI_BEHTYP2 <> 'OF'                 
           AND A.BOLAGKOD   IN ('TH')             
           AND A.PONR      <> 0                   
         ORDER BY A.PONR                         
         WITH UR                                 
 END-EXEC.                                       
                                                 
 EXEC SQL                                         
     DECLARE OLFALL1 CURSOR FOR                   
         SELECT C.PONR                           
               ,A.FNR                             
               ,A.REGTILLF                       
               ,A.KUNDNR                         
               ,CI_BEHTYP2                       
               ,BEGDATE                           
               ,DAYS(CURRENT DATE) - DAYS(BEGDATE)
               ,DAYS(CURRENT DATE) -             
               DAYS(VALUE(ANNUDATE,CURRENT DATE))
              ,BRANSCH                           
              ,FROMDATE                         
              ,TILLDATE                         
              ,UBEGDATE                         
              ,TARKOD                           
              ,C.BOLAGKOD                       
        FROM   TPY009OLFALL A                   
              ,TPY122FORSV C                     
        WHERE A.FNR      = C.FNR                 
          AND A.GRPNR    = C.GRPNR               
          AND A.OBJEKTNR = C.OBJEKTNR           
          AND A.REGTILLF = C.REGTILLF           
          AND A.BOLAGKOD = C.BOLAGKOD           
          AND C.PONR      <> 0                   
        ORDER BY C.PONR                         
        WITH UR                                 
END-EXEC.                                       
                                                 
EXEC SQL                                         
    DECLARE GRUPP1 CURSOR FOR                   
        SELECT B.PONR                           
              ,FNR                               
              ,CI_BEHTYP2                       
              ,FROMDATE                         
              ,TILLDATE                         
              ,UBEGDATE                         
              ,B.BOLAGKOD                       
        FROM   TPY122FORSV B                     
        WHERE B.BOLAGKOD IN ('TH') 
          AND B.BRANSCHGRP = 'GRUPP'
          AND B.BRANSCH    = '20'   
          AND B.PONR      <> 0     
        ORDER BY B.PONR             
        WITH UR                     
END-EXEC. 

Thanks,
Suresh
Back to top
View user's profile Send private message
ash_sudp
Beginner


Joined: 17 May 2006
Posts: 12
Topics: 0

PostPosted: Tue Sep 22, 2009 6:40 am    Post subject: Reply with quote

Hi Suresh,

I did not look at the SQL, but as a first step speak to your DBA to find out all the columns indexed on the table.

Reason:
If you do a order by OR any sort on the resultant on a non indexed column then you are doing a whole table scan. This will consume a lot of time. So check on the indexed part and see if the column in order by is a part of the primary index. If not see how it can be made a part of the promary index. This will help.

let me know if you need any more details.

Ashok Mohan.
Back to top
View user's profile Send private message
RonB
Beginner


Joined: 02 Dec 2002
Posts: 93
Topics: 0
Location: Orlando, FL

PostPosted: Tue Sep 22, 2009 8:20 am    Post subject: Reply with quote

I'm certainly no DB2 expert, but here's what I see after looking at the first cursor query, which was:

DECLARE KUND1 CURSOR FOR
SELECT DISTINCT A.PONR
,A.KUNDNR
,HUSHALLID
,A.BOLAGKOD
,YEAR(CURRENT DATE - FODELSEDATE)
,MONTH(CURRENT DATE - FODELSEDATE)
,DAVILLA
,CI_BRF
,A.LKFKOD
,A.LANSKOD
,A.KOMMUNKOD
,A.FORSAMLINGKOD
,SUBSTR(EMAILADRESS,1,50)
,A.POSTNR
,PKISTATUS
,A.CUSTOMERVALUE
FROM TPY001KUND A
WHERE EXISTS
(SELECT 1 FROM TPY122FORSV B
WHERE A.PONR = B.PONR
AND A.BOLAGKOD = B.BOLAGKOD
AND B.BRANSCHGRP IN
('CIVIL','MOTOR','OLFA','GRUPP'))
AND A.BOLAGKOD IN ('TH','AF')
AND A.PONR <> 0
AND FODELSEDATE <> ' '
AND A.REGTILLF IN
(SELECT MAX(REGTILLF)
FROM TPY001KUND C
WHERE C.PONR = A.PONR
AND C.BOLAGKOD = A.BOLAGKOD
AND C.BOLAGKOD IN ('TH','AF'))
ORDER BY A.PONR
WITH UR
END-EXEC.

First of all, having an ORDER BY A.PONR clause in addition to specifying DISTINCT A.PONR . . . A.CUSTOMERVALUE as the SELECT clause, is redundant since the DISTINCT clause implies that the resultant rows must be sorted in the order specified, and A.PONR is the first column selected in the DISTINCT clause.

Secondly, the WHERE C.BOLAGKOD IN ('TH','AF') predicate in the SELECT MAX inner join is redundant, since the inner join already tests WHERE C.BOLAGKOD = A.BOLAGKOD, and the inner join will only be executed if the WHERE A.BOLAGKOD IN ('TH','AF') predicates were met in the outer join.

Thirdly, DATE computations are costly and should be avoided, if possible. I'm not SURE, but I think that if you want both the year and the month from the same date computation, instead of saying YEAR(CURRENT DATE - FODELSEDATE) followed by MONTH(CURRENT DATE - FODELSEDATE), you could, instead, simply say SUBSTR(CHAR(CURRENT DATE - FODELSEDATE),1,4), thus reducing the number of date computations by half.

Fourthly, using an IN clause followed by a SELECT MAX clause is inefficient, since the MAX clause can only result in ONE value. The IN should be changed to a simple =.

And lastly, the WHERE clause should be tuned to eliminate matching rows as soon as possible, so you "could" eliminate the B.table access entirely if you eliminated A.rows early on. So, if it were me, I might consider rewriting the query as

Code:
SELECT DISTINCT A.PONR
               ,A.KUNDNR
               ,HUSHALLID
               ,A.BOLAGKOD
               ,SUBSTR(CHAR(CURRENT DATE - FODELSEDATE),1,4)
               ,DAVILLA
               ,CI_BRF
               ,A.LKFKOD
               ,A.LANSKOD
               ,A.KOMMUNKOD
               ,A.FORSAMLINGKOD
               ,SUBSTR(EMAILADRESS,1,50)
               ,A.POSTNR
               ,PKISTATUS
               ,A.CUSTOMERVALUE
  FROM TPY001KUND A
 WHERE A.PONR <> 0
   AND A.FODELSEDATE <> ' '
   AND A.BOLAGKOD    IN ('TH','AF')
   AND A.REGTILLF     =
      (SELECT MAX(C.REGTILLF)
         FROM TYP001KUND C
        WHERE C.PONR     = A.PONR
          AND C.BOLAGKOD = A.BOLAGKOD)
   AND EXISTS
      (SELECT 1 FROM TPY122FORSV B
        WHERE B.PONR        = A.PONR
          AND B.BOLAGKOD    = A.BOLAGKOD
          AND B.BRANSCHGRP IN
             ('CIVIL','MOTOR','OLFA','GRUPP'))
  WITH UR


Just my thoughts - I could be way off base.
As I said, I don't pretend to be any kind of expert on DB2.
Of course, regression testing should be done to insure that any "tuned" query yields the desired results.
Back to top
View user's profile Send private message
bauer
Intermediate


Joined: 10 Oct 2003
Posts: 317
Topics: 50
Location: Germany

PostPosted: Wed Sep 23, 2009 1:23 am    Post subject: Reply with quote

Use EXPLAIN, check runstats data.
Back to top
View user's profile Send private message
suresh_d
Beginner


Joined: 20 Sep 2006
Posts: 33
Topics: 9

PostPosted: Wed Sep 23, 2009 4:34 am    Post subject: The problem is with first cursor. Reply with quote

Hi,

Yes the problem si with first cursor kund1, I was able to understand your tuned queryt except the date part. I guess the above tuned date will result only year ? how to fetch the month part also ina single date command.

I am begineer in DB2 tuning, plz don't mistake if I didn't understand.

Thank you.
Suresh
Back to top
View user's profile Send private message
RonB
Beginner


Joined: 02 Dec 2002
Posts: 93
Topics: 0
Location: Orlando, FL

PostPosted: Wed Sep 23, 2009 6:54 am    Post subject: Reply with quote

Ah yes. My apologies. I see that I neglected to remember that DB2 formats the date in character mode as yyyy DASH mm DASH dd, while the YEAR function returns positions 1-4 and the MONTH returns positions 6-7. My SUBSTR(CHAR(*),1,4) was predicated on my poor brain's false idea that the returned date would be like COBOL returns it, namely YYMMDD.
If you can live with YYYY-MM, you could change the SUBSTR length from 4 to 7. If not, then you will have to leave the query with both YEAR(*) and MONTH(*), though, as I said, date calculations are quite expensive in queries. I have seen situations where it was much faster and far more efficient to return the entire date ( with the calculation ) in the original query, followed by a SORT step that copies the output, selecting only the required fields, to create the ultimate desired output. The savings becomes more evident as the number of rows returned increases. It's not such a big deal if there are only a few hundred rows, but at 100,000 rows, it is a big deal.
_________________
A computer once beat me at chess, but it was no match for me at kick boxing.
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic   printer-friendly view    MVSFORUMS.com Forum Index -> Database All times are GMT - 5 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


MVSFORUMS
Powered by phpBB © 2001, 2005 phpBB Group