2016-11-11 3 views
1

Ich habe die unten Abfrage, die lange Ausführungszeit dauert ca. 20 Minuten für eine Reihe von Zeile 1345222. Ich habe eine Möglichkeit, dies zu tun, vor allem die Beteiligt-Vergleich?Zwischen länger dauern. Tuning SQL-Abfrage

<code> 
SELECT /*+ PARALLEL(32) */ upexp.item, 
        upexp.loc, 
        startdate, 
        sku_exp.bucket_size, 
        MAX(upexp.sku_multiplier) OVER (PARTITION BY upexp.item,upexp.loc) max_sm 
         FROM 
           (SELECT bucket bkt, 
             MIN(dates) OVER (PARTITION BY bucket) minbk, 
             MAX(dates) OVER (PARTITION BY bucket) maxbk 
           FROM (
             SELECT LEVEL AS sl, 
             NEXT_DAY (TRUNC (SYSDATE, 'YEAR') + 7 * LEVEL - 8,'SATURDAY') AS dates, 
             CEIL (LEVEL/4) AS bucket 
             FROM DUAL 
             CONNECT BY LEVEL <= ((4 - MOD (78, 4) + 78) + 78)) yy 
           -- GROUP BY bucket 
           ) minmaxdate , 
         stsc.u_promo_sku_expand sku_exp, 
         stsc.u_promo_upload_expand upexp 
         WHERE sku_exp.bucket_size = 4 
         AND sku_exp.startdate BETWEEN minmaxdate.minbk AND minmaxdate.maxbk 
         AND upexp.item = sku_exp.item 
         AND upexp.loc = sku_exp.loc 
         AND upexp.u_country = sku_exp.u_country 
         AND ((eff BETWEEN minmaxdate.minbk AND minmaxdate.maxbk+6) 
         OR (disc BETWEEN minmaxdate.minbk AND minmaxdate.maxbk+6) 
         OR (eff <= minmaxdate.minbk AND disc >= minmaxdate.maxbk+6)) 

</code> 
+1

Wo ist der Plan? '(eff BETWEEN minmaxdate.minbk UND minmaxdate.maxbk + 6) oder eff <= minmaxdate.minbk UND disc> = minmaxdate.maxbk + 6)' im letzten Prädikat ist in jedem Fall wahr –

+0

Haben Sie einen Index für die aktuelle Tabellen? Außerdem verstehe ich nicht ganz, warum Sie die SELECT ... FROM DUAL in der gesamten Abfrage haben. Kannst du es nicht rausbringen? – FDavidov

+0

versuchen Sie mit Gruppe durch beide anstelle von MIN/MAX OVER. Und ziehe die Verbindung per Abfrage in eine WITH – Thomas

Antwort

0

Dieser Block

(SELECT bucket bkt, 
    MIN(dates) OVER (PARTITION BY bucket) minbk, 
    MAX(dates) OVER (PARTITION BY bucket) maxbk 
FROM (
    SELECT LEVEL AS sl, 
     NEXT_DAY (TRUNC (SYSDATE, 'YEAR') + 7 * LEVEL - 8,'SATURDAY') AS dates, 
     CEIL (LEVEL/4) AS bucket 
    FROM DUAL 
    CONNECT BY LEVEL <= ((4 - MOD (78, 4) + 78) + 78)) yy 
    -- GROUP BY bucket 
    ) 

scheint nutzlos zu sein, da man nur Min- und Max-Wert benötigen.

Versuchen Sie dieses:

WITH minmaxdate AS 
    (SELECT 
     NEXT_DAY (TRUNC (SYSDATE, 'YEAR') + 7 * 1 - 8,'SATURDAY') AS minbk, 
     NEXT_DAY (TRUNC (SYSDATE, 'YEAR') + 7 * ((4 - MOD (78, 4) + 78) + 78) - 8,'SATURDAY') AS maxbk 
    FROM dual) 
SELECT item, loc, startdate, sku_exp.bucket_size, 
    MAX(upexp.sku_multiplier) OVER (PARTITION BY item, loc) max_sm 
FROM stsc.u_promo_sku_expand sku_exp 
    JOIN stsc.u_promo_upload_expand upexp USING (item, loc, u_country) 
    CROSS JOIN minmaxdate 
WHERE sku_exp.bucket_size = 4 
    AND sku_exp.startdate BETWEEN minmaxdate.minbk AND minmaxdate.maxbk 
    AND (
     eff BETWEEN minmaxdate.minbk AND minmaxdate.maxbk+6 
     OR (eff <= minmaxdate.minbk AND disc >= minmaxdate.maxbk+6) 
     OR disc BETWEEN minmaxdate.minbk AND minmaxdate.maxbk+6 
    ); 
+0

Ich bekomme das: ORA-25154: Spalte Teil der USING-Klausel kann kein Qualifikationsmerkmal haben. ABER DAS FUNKTIONIERT GUT. SELECT item, loc, startdatum, bucket_size - MAX (sku_multiplier) OVER (PARTITION VON sku_exp.item, sku_exp.loc) max_sm FROM stsc.u_promo_sku_expand sku_exp JOIN stsc.u_promo_upload_expand upexp VERWENDUNG (item, loc, u_country) WHERE sku_exp.bucket_size = 4 –