Abfrageperformance

max050180

Benutzer
Beiträge
12
Hallo zusammen,

ich habe bereits im Bereich mysql eine Frage zu einer Abfrage gestellt, aber mir wurde da mitgeteilt, dass ich hier mit Oracle besser aufgehoben bin. Ich habe folgendes "Problem" mit der Performance einer Abfrage.

Zur Erklärung: Mit ID ist eine Teilenummer gemeint und mit Wert ein Messwert und mit Operation eine Messoperation. Das Teil kann an mehreren Operationen gemessen werden

Die Ausgangsabfrage ist folgende...

PHP:
WITH 

u2(Zeile,ID,Warp,operation,waf_Flag) AS (

  SELECT
       ROW_NUMBER() OVER (PARTITION BY w.ID ORDER BY adel.operation) AS Zeile
       ,w.ID
       ,adew.warp
       ,adel.operation
       ,adew.waf_flag
  FROM 
      LOADER.WAFERS w
      INNER JOIN LOADER.LWADE_WAFERS adew ON w.sid = adew.waf_sid
      INNER JOIN LOADER.LWADE_LOTS adel ON adew.lothis_sid = adel.lothis_sid
      )
    
SELECT 
  u2.Zeile
  ,w.ID
  ,u2.operation
  ,u2.warp as Wert
FROM 
  LOADER.WAFERS w
  INNER JOIN MPPDBB_OWNER.ingot_segments ise ON ise.ingot_seg = w.ingot_seg and w.id in 'MW2033117686'
    LEFT JOIN u2 ON w.ID = u2.ID

...mit dieser erhalte ich folgendes Ergebnis nach ca. 0,01 Sekunden:

ZEILE | ID | OPERATION | Wert
1 | MW2033117686 | 5040 | 7,2
2 | MW2033117686 | 8340 | 5,3

Da ich aber folgendes Ergebnis möchte..

ID | OPERATION_1 | Wert_1 |OPERATION_2 | Wert_2
MW2033117686 | 5040 | 7,2 | 8340 | 5,3

...habe ich nach einem Vorschlag den select-Teil folgendermaßen abgeändert, wobei der Rest unverändert bleibt.

PHP:
SELECT   

  w.ID
  ,u2.operation as Operation_1
  ,u2.warp as Wert_1
  ,u3.operation as Operation_2
  ,u3.warp as Wert_2
FROM 
  LOADER.WAFERS w
  INNER JOIN MPPDBB_OWNER.ingot_segments ise ON ise.ingot_seg = w.ingot_seg and w.id in 'MW2033117686'
  LEFT JOIN u2 ON w.ID = u2.ID AND u2.zeile = '1'
  LEFT JOIN u2 u3 ON w.ID = u3.ID AND u3.zeile = '2'

Das Ergebnis wird auch ausgegeben, allerdings werden fast 50 Sekunden dafür benötigt.

Wie kann ich die Abfrage ändern, damit sie schneller läuft.


Gruß, Matthias
 
Werbung:
Packe die erste abfrage in ein WITH, nenne dieses z.B. max05. Dann kannst Du darauf ausführen:

Code:
test=*# select * from max05 ;
 zeile |  id  | operation | wert
-------+--------------+-----------+------
  1 | MW2033117686 |  5040 |  7.2
  2 | MW2033117686 |  8340 |  5.3
(2 Zeilen)

test=*# select id, sum(case when zeile = 1 then operation else null end) as operation_1, sum(case when zeile = 1 then wert else null end) as wert_1, sum(case when zeile=2 then operation else null end) as operation_2, sum(case when zeile=2 then wert else null end) as wert_2 from max05 group by id;
  id  | operation_1 | wert_1 | operation_2 | wert_2
--------------+-------------+--------+-------------+--------
 MW2033117686 |  5040 |  7.2 |  8340 |  5.3
(1 Zeile)

test=*#
 
Das mit dem WITH hat er schon gemacht, ist der Code aus einem anderen Thread. Im WITH ist es interessanter Weise essentiell langsammer als wenn er es (mehrfach!) als Subquery aufruft.

EXPLAIN ist angebracht aber ganz erlich dafür kenne ich Oracle nicht genug um die Ursache zu erraten.
 
Zumindest in PostgreSQL ist es (derzeit noch) so, daß WITH-Abfragen, die im WITH große Ergebnissmengen haben, mitunter langsammer sind. Insbesondere dann, wenn auf das Resultat dieser Abfragen dann später noch WHERE-Conditions kommen - diese werden (zumindest derzeit) nicht auf den WITH-Teil 'durchgereicht'.

Darum geht es aber hier nicht. Er hat hier zuerst eine Abfrage gezeigt, die hinreichend schnell ist, 0,01 Sekunde. Sie liefert 2 Zeilen. Das kann man verschacheln, wiederum als WITH, und darauf die von ihm gewünschte Aggregation machen. Das ist das, was ich zeigen wollte. Das als WITH zu schreiben ist nicht zwingend, könnte auch umgeschrieben werden als normale abfrage (select ... from (hier seine bisherige Abfrage) as ...
 
Hallo zusammen,
da hier der Begriff "EXPLAIN" genannt wurde, habe ich mich zumindest soweit belesen, dass ich mir zu den beiden Abfragen ein paar Daten ausgeben konnte. Ich habe die Daten als PDF-Datei angehängt. Die Datei Teil 1 bezieht sich auf folgende Abfrage:
PHP:
WITH 


u2 (Zeile,ID,Warp,operation,waf_Flag) AS (

  SELECT 
       ROW_NUMBER() OVER (PARTITION BY w.ID ORDER BY adel.operation) AS Zeile
       ,w.ID
       ,adew.warp
       ,adel.operation
       ,adew.waf_flag
  FROM  
      LOADER.WAFERS w
      INNER JOIN LOADER.LWADE_WAFERS adew ON w.sid = adew.waf_sid and adew.waf_flag_context = 'GEO-RC1'
      INNER JOIN LOADER.LWADE_LOTS adel ON adew.lothis_sid = adel.lothis_sid
      )
     
SELECT  

  w.ID
  ,u2.operation
  ,u2.warp as Warp_1

FROM  
  LOADER.WAFERS w
  INNER JOIN MPPDBB_OWNER.ingot_segments ise ON ise.ingot_seg = w.ingot_seg and w.id in 'MW2033117686'
 
  LEFT JOIN u2 ON w.ID = u2.ID

und die Datei Teil 2 auf folgende Abfrage:

PHP:
WITH 


u2 (Zeile,ID,Warp,operation,waf_Flag) AS (

  SELECT 
  ROW_NUMBER() OVER (PARTITION BY w.ID ORDER BY adel.operation) AS Zeile
  ,w.ID
  ,adew.warp
  ,adel.operation
  ,adew.waf_flag
  FROM 
  LOADER.WAFERS w
  INNER JOIN LOADER.LWADE_WAFERS adew ON w.sid = adew.waf_sid and adew.waf_flag_context = 'GEO-RC1'
  INNER JOIN LOADER.LWADE_LOTS adel ON adew.lothis_sid = adel.lothis_sid
  )
 
SELECT 
  w.ID
  ,u2.operation
  ,u2.warp as Warp_1
  ,u3.operation
  ,u3.warp as Warp_2

FROM 
  LOADER.WAFERS w
  INNER JOIN MPPDBB_OWNER.ingot_segments ise ON ise.ingot_seg = w.ingot_seg and w.id in 'MW2033117686'
 
  LEFT JOIN u2 ON w.ID = u2.ID AND u2.zeile = '1'
  LEFT JOIN u2 u3 ON w.ID = u3.ID AND u3.zeile = '2'

Ich kann mit den Angaben in den PDF-Files nur wenig anfangen, aber ihr habt da sicherlich mehr Ahnung.

Gruß, Matthias
 

Anhänge

  • Teil 1.pdf
    38,8 KB · Aufrufe: 6
  • Teil 2.pdf
    39,6 KB · Aufrufe: 6
Werbung:
Also im Teil 2 sehe ich 82 Terra Rows mit 8969TB Größe. Sportlich. Ich bin aber mit Oracle jetzt nicht weiter vertraut, um das näher zu deuten. Möglicherweise völlig kaputte Statistiken.
 
Zurück
Oben