Optymalizacja zapytania

0

Witam, mam taki problem, robie dosc zlozone zapytanie i w cześci WHERE musialem zamienic AND na OR. Z AND zapytanie wykonywalo sie kilka minut, natomiast z OR ten czas to ponad 2h. W jaki sposob zoptymalizowac zapytanie, zeby wykonalo sie rowniez w pare minut (danych jest bardzo duzo)? Prosze o wszelkie pomysly jak to zrobic.


select  distinct  e.umowa,b.statum,b.wartof,a.stid,a.statst,a.grupa,a.wartosc, 
         coalesce(pd.sumpd, 0) as sumpd, coalesce(npd.sumnpd, 0) as sumnpd, coalesce(inne.sumin, 0) as sumin , 
         (a.wartosc -  coalesce(pd.sumpd, 0) - coalesce(npd.sumnpd, 0) - coalesce(inne.sumin, 0)) as roznica
         

from ((((((DROLEASEF2.PLST01PF a inner join DROLEASEF2.pled02pf b on a.umowa = b.umowa)  
        inner join DROLEASEF2.plst60pf c on a.stid = c.stid)                   
        inner join DROLEASEF2.plfk09pf e on e.umowa = b.umowa)                   
        inner join DROLEASEF2.plfk08pf f on e.idoc = f.docnbr and                
                                                          e.ipoz = f.poznbr)                 
                  

left  join
                          
          
               (select e.umowa,b.statum,b.wartof,a.stid,a.statst,a.grupa,a.wartosc,
                         sum(f.winien - f.ma)  as sumpd

                 from ((((DROLEASEF2.plst01pf a inner join DROLEASEF2.pled02pf b on a.umowa = b.umowa)   
                   inner join DROLEASEF2.plst60pf c on a.stid = c.stid)                                                       
                   inner join DROLEASEF2.plfk09pf e on e.umowa = b.umowa)                   
                   inner join DROLEASEF2.plfk08pf f on e.idoc = f.docnbr and                
                                                                      e.ipoz = f.poznbr)                 
                 where e.invid < 0 and f.acc1 = '03081' and 
                           exists(select g.stid, g.invid from DROLEASEF2.plst31pf g where e.invid = g.invid and      
                                    g.stid = a.stid and g.invid <0) 
                  group by e.umowa,b.statum,b.wartof,a.stid,a.statst, a.grupa,a.wartosc)  pd

on pd.umowa = e.umowa and pd.stid = a.stid)

left join

           (select e.umowa,b.statum,b.wartof,a.stid,a.statst,a.grupa,a.wartosc,
                      sum(f.winien - f.ma)  as sumnpd

                from ((((DROLEASEF2.plst01pf a inner join DROLEASEF2.pled02pf b on a.umowa = b.umowa)   
                   inner join DROLEASEF2.plst60pf c on a.stid = c.stid)                        
                   inner join DROLEASEF2.plfk09pf e on b.umowa = e.umowa)                   
                   inner join DROLEASEF2.plfk08pf f on e.idoc = f.docnbr and                
                                                                      e.ipoz = f.poznbr) 
                  where  f.acc1 = '03081' and e.invid < 0 and not exists (select g.stid, g.invid from DROLEASEF2.plst31pf g where e.invid =  
                             g.invid and g.stid = a.stid and g.invid <0) 
                  group by e.umowa,b.statum,b.wartof,a.stid,a.statst, a.grupa,a.wartosc)  npd

on npd.umowa = e.umowa and npd.stid = a.stid)


left join
         
     (select e.umowa,b.statum,b.wartof,a.stid,a.statst,a.grupa,a.wartosc,
                      sum(f.winien - f.ma)  as sumin

                from (((((DROLEASEF2.plst01pf a inner join DROLEASEF2.pled02pf b on a.umowa = b.umowa)   
                   inner join DROLEASEF2.plst60pf c on a.stid = c.stid)                        
                   inner join DROLEASEF2.plfk09pf e on b.umowa = e.umowa)                   
                   inner join DROLEASEF2.plfk08pf f on e.idoc = f.docnbr and                
                                                                       e.ipoz = f.poznbr) 
                  inner join DROLEASEF2.plfk07pf g on g.docnbr = f.docnbr and
                                                                      g.poznbr = f.poznbr)
                  where  f.acc1 = '03081' and g.zaptyp not in (-1, -3, -4) and e.invid < 0 
                  group by e.umowa,b.statum,b.wartof,a.stid,a.statst,               
                               a.grupa,a.wartosc)  inne

on inne.umowa = e.umowa and npd.stid = a.stid



where  ((npd.sumnpd <> 0) or (a.wartosc -  coalesce(pd.sumpd, 0) - coalesce(npd.sumnpd, 0) - coalesce(inne.sumin, 0)) <> 0)
             and a.protdt  between 1101111 and 1141111


  
order by e.umowa, a.stid;


0

i jak ty sobie to wyobrażasz, że ktoś coś zrobi z tym zapytaniem??? Przede wszystkim potrzebny jest plan zapytania - google wie jak go pozyskać.
Przecież to nawet jakoś sensownie sformatowane nie jest

BTW kod daje się w treści posta

0

Jak już napisał poprzednik nie jestem w stanie przebić się przez Twoje zapytanie. Możesz spróbować zamienić "or" na "and" w ten sposób (Prawa De Morgana):

zamiast:

A OR B

piszesz:

!(!A AND !B)

Jednakże nie jestem w stanie zagwarantować w jakim stopniu to poprawi wydajność w Twoim konkretnym przypadku.

0

Na początek sformatowane zapytanie:

SELECT DISTINCT e.umowa,
                b.statum,
                b.wartof,
                a.stid,
                a.statst,
                a.grupa,
                a.wartosc,
                COALESCE(pd.sumpd, 0) AS sumpd,
                COALESCE(npd.sumnpd, 0) AS sumnpd,
                COALESCE(inne.sumin, 0) AS sumin,
                (a.wartosc - COALESCE(pd.sumpd, 0) - COALESCE(npd.sumnpd, 0) - COALESCE(inne.sumin, 0)) AS roznica
FROM ((((((DROLEASEF2.PLST01PF a
           INNER JOIN DROLEASEF2.pled02pf b ON a.umowa = b.umowa)
          INNER JOIN DROLEASEF2.plst60pf c ON a.stid = c.stid)
         INNER JOIN DROLEASEF2.plfk09pf e ON e.umowa = b.umowa)
        INNER JOIN DROLEASEF2.plfk08pf f ON e.idoc = f.docnbr
        AND e.ipoz = f.poznbr)
       LEFT  JOIN
         (SELECT e.umowa,
                 b.statum,
                 b.wartof,
                 a.stid,
                 a.statst,
                 a.grupa,
                 a.wartosc,
                 SUM(f.winien - f.ma) AS sumpd
          FROM ((((DROLEASEF2.plst01pf a
                   INNER JOIN DROLEASEF2.pled02pf b ON a.umowa = b.umowa)
                  INNER JOIN DROLEASEF2.plst60pf c ON a.stid = c.stid)
                 INNER JOIN DROLEASEF2.plfk09pf e ON e.umowa = b.umowa)
                INNER JOIN DROLEASEF2.plfk08pf f ON e.idoc = f.docnbr
                AND e.ipoz = f.poznbr)
          WHERE e.invid < 0
            AND f.acc1 = '03081'
            AND EXISTS
              (SELECT g.stid, g.invid
               FROM DROLEASEF2.plst31pf g
               WHERE e.invid = g.invid
                 AND g.stid = a.stid
                 AND g.invid <0)
          GROUP BY e.umowa,
                   b.statum,
                   b.wartof,
                   a.stid,
                   a.statst,
                   a.grupa,
                   a.wartosc) pd ON pd.umowa = e.umowa
       AND pd.stid = a.stid)
      LEFT JOIN
        (SELECT e.umowa,
                b.statum,
                b.wartof,
                a.stid,
                a.statst,
                a.grupa,
                a.wartosc,
                SUM(f.winien - f.ma) AS sumnpd
         FROM ((((DROLEASEF2.plst01pf a
                  INNER JOIN DROLEASEF2.pled02pf b ON a.umowa = b.umowa)
                 INNER JOIN DROLEASEF2.plst60pf c ON a.stid = c.stid)
                INNER JOIN DROLEASEF2.plfk09pf e ON b.umowa = e.umowa)
               INNER JOIN DROLEASEF2.plfk08pf f ON e.idoc = f.docnbr
               AND e.ipoz = f.poznbr)
         WHERE f.acc1 = '03081'
           AND e.invid < 0
           AND NOT EXISTS
             (SELECT g.stid,
                     g.invid
              FROM DROLEASEF2.plst31pf g
              WHERE e.invid = g.invid
                AND g.stid = a.stid
                AND g.invid <0)
         GROUP BY e.umowa,
                  b.statum,
                  b.wartof,
                  a.stid,
                  a.statst,
                  a.grupa,
                  a.wartosc) npd ON npd.umowa = e.umowa
      AND npd.stid = a.stid)
LEFT JOIN
  (SELECT e.umowa,
          b.statum,
          b.wartof,
          a.stid,
          a.statst,
          a.grupa,
          a.wartosc,
          SUM(f.winien - f.ma) AS sumin
   FROM (((((DROLEASEF2.plst01pf a
             INNER JOIN DROLEASEF2.pled02pf b ON a.umowa = b.umowa)
            INNER JOIN DROLEASEF2.plst60pf c ON a.stid = c.stid)
           INNER JOIN DROLEASEF2.plfk09pf e ON b.umowa = e.umowa)
          INNER JOIN DROLEASEF2.plfk08pf f ON e.idoc = f.docnbr
          AND e.ipoz = f.poznbr)
         INNER JOIN DROLEASEF2.plfk07pf g ON g.docnbr = f.docnbr
         AND g.poznbr = f.poznbr)
   WHERE f.acc1 = '03081'
     AND g.zaptyp NOT IN (-1,
                          -3,
                          -4)
     AND e.invid < 0
   GROUP BY e.umowa,
            b.statum,
            b.wartof,
            a.stid,
            a.statst,
            a.grupa,
            a.wartosc) inne ON inne.umowa = e.umowa
AND npd.stid = a.stid
WHERE ((npd.sumnpd <> 0)
       OR (a.wartosc - COALESCE(pd.sumpd, 0) - COALESCE(npd.sumnpd, 0) - COALESCE(inne.sumin, 0)) <> 0)
  AND a.protdt BETWEEN 1101111 AND 1141111
ORDER BY e.umowa,
         a.stid;

// @somekind, możesz przpiąć do pierwszego posta i ten usunąć?

0

Niepokoi mnie duża ilość inner join-ów, które się powtarzają. Jak dobrze licze masz trzykrotnie powtórzoną strukturę:

DROLEASEF2.PLST01PF a
           INNER JOIN DROLEASEF2.pled02pf b ON a.umowa = b.umowa)
          INNER JOIN DROLEASEF2.plst60pf c ON a.stid = c.stid)
         INNER JOIN DROLEASEF2.plfk09pf e ON e.umowa = b.umowa)
        INNER JOIN DROLEASEF2.plfk08pf f ON e.idoc = f.docnbr
        AND e.ipoz = f.poznbr

Pierwsze co bym tu zrobił to użycie Materialized Query Table jeszcze przed wykonaniem głównego raportu w celu wygenerowania raportu cześciowego. Następnie można na taki widok (bo jest to odpowiednich oraclowego materialized view) można nakładać ograniczenia, które będą już lżejsze.

0

chopie, tak się nie pisze, bo komu potem będzie się chciało to rozczytywać po Tobie, żeby poprawić?
Nie jest przejrzyste. Lepiej robić po drodze tabelki tymczasowe i takie zapytanie zrobić w 3-4 krokach.

1 użytkowników online, w tym zalogowanych: 0, gości: 1