Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   SQL Sauert zu lange (https://www.delphipraxis.net/189544-sql-sauert-zu-lange.html)

Dumpfbacke 23. Jun 2016 06:24

Datenbank: Firebird • Version: 2.5 • Zugriff über: IBX

SQL Sauert zu lange
 
Hallo Delphianer,
ich habe ein Problem mit einem Select. Deshalb habe ich hier unten mal einen Auszug als dem Select eingestellt. Das Problem liegt hier bei or (UrMaster.referenznr = 'ABT_25' ).

Auf allen Feldern in der Where liegt ein Index auch auf der RefernzNr.

Wenn ich das ganze ohne die letzte Zeile mache mache dauert es ca. 2 Sekunden. Mit dieser Bedingung dauert es ca. 22 Sekunden. Wenn ich das danze richtig deute (bei IBExpert) wird hier der Index nicht benutzt.

Ich muss die Joins so machen da ich daten aus den entsprechenden Tabellen benötige.

Kann mit jemand von Euch hier helfen ?

Danke schon einmal Tanja

Delphi-Quellcode:


from MASTER
Left Outer JOIN SLAVE on MASTER.Vorgangsnummer = SLAVE.Vorgangsnummer and (SLAVE.ZusatzStatus = 'EZ' or SLAVE.ZusatzStatus = 'EV' or
                                                                    SLAVE.ZusatzStatus = 'EF' or SLAVE.ZusatzStatus = 'EA' or
                                                                    SLAVE.ZusatzStatus = 'EQ' or SLAVE.ZusatzStatus = 'EP')
Left Outer Join MASTER UrMaster on MASTER.Vorgangursprung = UrMaster.Vorgangsnummer
where MASTER.Status = 'In Bearbeitung' and SLAVE.SlaveNummerr is not NULL
and ((SLAVE.SlaveStatus = 'Warten' or SLAVE.SlaveStatus = 'Unterbrochen' or
      SLAVE.SlaveStatus = 'In Arbeit' and SLAVE.Dzusatz is NULL) or
     (SLAVE.SlaveStatus = 'In Abreit' and SLAVE.Dzusatz = 'Gesperrt' and
      SLAVE.Sollende < Current_Date)
    )

    and
    MASTER.FATW = 'Aktive'
and (((MASTER.AltesSystem like 'Start%' or MASTER.AltesSystem like 'Vorgang%' )
       and MASTER.AltesSystem not like '%Abbruch%' and MASTER.Storno is null
     )
    or (UrMaster.referenznr = 'ABT_25' )  )

jobo 23. Jun 2016 07:40

AW: SQL Sauert zu lange
 
Wie groß ist die Basismenge der einzelnen Tabellen und wie groß ca das Ergebnis?
Auf die Schnelle schon mal:
Feste Kriterien wenn mgl. z.B. bei Slave mit in den Join reinpacken (auch wenn es nicht zum Join gehört)
Zitat:

MASTER.AltesSystem not like '%Abbruch%
Möglich kein % am Anfang, bester alle '%Abbruch' Varianten analysieren und aufführen (falls das statisch ist bzw. bleibt)
Bei dem Or von URMASTER sehe ich auf den ersten Blick keinen Ausweg. Muss es wirklich ein Left Outer Join zu Master sein?

nahpets 23. Jun 2016 07:47

AW: SQL Sauert zu lange
 
Habe das Statement einmal strukturell verändert, um es für mich lesbarer zu machen.

Dabei hab' ich (nach meinem Verständnis) Vereinfachungen eingebaut und Verständnisprobleme mit Kommentaren versehen.

Allerdings habe ich keine Ahnung, ob das irgendwas am Geschwindigkeitsproblem ändert.
SQL-Code:
from MASTER
Left Outer JOIN SLAVE
on  MASTER.Vorgangsnummer = SLAVE.Vorgangsnummer
and SLAVE.ZusatzStatus in ('EZ','EV','EF','EA','EQ','EP')
Left Outer Join MASTER UrMaster
on   MASTER.Vorgangursprung = UrMaster.Vorgangsnummer
where MASTER.Status     = 'In Bearbeitung'
and  SLAVE.SlaveNummerr is not NULL
and MASTER.FATW = 'Aktive'
and
    (
     -- Beginn Verständnisproblem
     -- Hier verstehe ich nicht genau, was gemeint ist und weiß nicht, wie FireBird das handhabt.
     -- Das Is Null bezieht sich nur auf Status = 'In Arbeit'?
     (   SLAVE.SlaveStatus in ('Warten','Unterbrochen')
      or SLAVE.SlaveStatus = 'In Arbeit' and SLAVE.Dzusatz is NULL
      -- Bei Is Null-Bezug nur auf 'In Arbeit' würd' ich das in Klammern setzen.
      or (SLAVE.SlaveStatus = 'In Arbeit' and SLAVE.Dzusatz is NULL)
     )
     -- oder ist dieses gemeint?
     (
          SLAVE.SlaveStatus in ('Warten','Unterbrochen','In Arbeit')
      and SLAVE.Dzusatz is NULL
     )
     -- Ende Verständnisproblem
     
     or (    SLAVE.SlaveStatus = 'In Abreit' <-- Schreibfehler? 'In Arbeit'
         and SLAVE.Dzusatz = 'Gesperrt'
         and SLAVE.Sollende < Current_Date
        )
    )
and
    (
     (
      (
          MASTER.AltesSystem like 'Start%'
       or MASTER.AltesSystem like 'Vorgang%'
      )
      and MASTER.AltesSystem not like '%Abbruch%'
      and MASTER.Storno     is null
     )
     or (UrMaster.referenznr = 'ABT_25')
    )
Dann hätte ich noch ein fachliches Problem:
Worauf bezieht sich das UrMaster.referenznr = 'ABT_25' im zweiten Left outer Join.
Irgendwie kann ich an der Stelle, an der die Oder-Bedingung für die 'ABT_25' steht, nicht so recht den Sinn erkennen.

Es findet eine Grundsätzliche Verbindung über MASTER.Vorgangursprung = UrMaster.Vorgangsnummer statt.
Es gibt ein paar Einschränkungen und die letzte Einschränkung gilt für AltesSystem like 'Start%' oder like 'Vorgang%', sofern nicht AltesSystem like '%Abbruch% und Storno is null, wobei diese Einschränkung nicht für die 'Abt_25' gilt.
D. h.: Für 'Abt_25' sollen die Daten auch geliefert werden, wenn AltesSystem like 'Start%' oder like 'Vorgang%' ...?

sh17 23. Jun 2016 08:01

AW: SQL Sauert zu lange
 
wer lässt denn auch eine SQL-Abfrage versauern :-D

ibp 23. Jun 2016 08:20

AW: SQL Sauert zu lange
 
Zitat:

Zitat von sh17 (Beitrag 1340844)
wer lässt denn auch eine SQL-Abfrage versauern :-D

das ganze ist unausgegoren :-D

jobo 23. Jun 2016 08:31

AW: SQL Sauert zu lange
 
Zitat:

Zitat von nahpets (Beitrag 1340843)
SQL-Code:
and SLAVE.ZusatzStatus in ('EZ','EV','EF','EA','EQ','EP')

Ich bin kein Firebird Spezialist, aber "in ()" oder "or" wird doch sehr wahrscheinlich intern gleich abgearbeitet? Wäre also nur besser für die Augen.

Ja und "sauer macht lustig", wollte ich schon immer mal loswerden.
Nicht dass wir die Sache am Ende mit zuviel unnötigem Ernst angehen. ;)

nahpets 23. Jun 2016 08:39

AW: SQL Sauert zu lange
 
Zitat:

Zitat von jobo (Beitrag 1340849)
Zitat:

Zitat von nahpets (Beitrag 1340843)
SQL-Code:
and SLAVE.ZusatzStatus in ('EZ','EV','EF','EA','EQ','EP')

Ich bin kein Firebird Spezialist, aber "in ()" oder "or" wird doch sehr wahrscheinlich intern gleich abgearbeitet? Wäre also nur besser für die Augen.

Das mag durchaus so sein, aber durch erhöhte Lesbarkeit hab' ich in der Vergangenheit schon des Öftern fachliche Fehler finden können, die ansonsten nicht auffielen. Gerade bei vielen and und or kann es schonmal schnell passieren, das eine Klammerung knapp daneben ging, auch wenn das Statement syntaktisch weiterhin korrekt war.
Und so knapp daneben liegende Klammern können schonmal schnell zu einer exorbitant steigenden Laufzeit führen.

Und letztlich resultieren meine Fragen zum "threadauslösenden" SQL ja auch daher.

ibp 23. Jun 2016 08:56

AW: SQL Sauert zu lange
 
Zitat:

Zitat von Dumpfbacke (Beitrag 1340836)
...
Wenn ich das ganze ohne die letzte Zeile mache mache dauert es ca. 2 Sekunden. Mit dieser Bedingung dauert es ca. 22 Sekunden.

Wie lange dauert es denn, wenn du die Abfrage nur mit der letzten Bedingung (Zeile) absendest?

SQL-Code:
from MASTER
Left Outer JOIN SLAVE on MASTER.Vorgangsnummer = SLAVE.Vorgangsnummer and (SLAVE.ZusatzStatus = 'EZ' or SLAVE.ZusatzStatus = 'EV' or
                                                                    SLAVE.ZusatzStatus = 'EF' or SLAVE.ZusatzStatus = 'EA' or
                                                                    SLAVE.ZusatzStatus = 'EQ' or SLAVE.ZusatzStatus = 'EP')
Left Outer Join MASTER UrMaster on MASTER.Vorgangursprung = UrMaster.Vorgangsnummer
where (UrMaster.referenznr = 'ABT_25' )

nahpets 23. Jun 2016 09:23

AW: SQL dauert zu lange
 
Zitat:

Zitat von ibp (Beitrag 1340852)
Zitat:

Zitat von Dumpfbacke (Beitrag 1340836)
...
Wenn ich das ganze ohne die letzte Zeile mache mache dauert es ca. 2 Sekunden. Mit dieser Bedingung dauert es ca. 22 Sekunden.

Wie lange dauert es denn, wenn du die Abfrage nur mit der letzten Bedingung (Zeile) absendest?
SQL-Code:
from MASTER
Left Outer JOIN SLAVE on MASTER.Vorgangsnummer = SLAVE.Vorgangsnummer and (SLAVE.ZusatzStatus = 'EZ' or SLAVE.ZusatzStatus = 'EV' or
                                                                    SLAVE.ZusatzStatus = 'EF' or SLAVE.ZusatzStatus = 'EA' or
                                                                    SLAVE.ZusatzStatus = 'EQ' or SLAVE.ZusatzStatus = 'EP')
Left Outer Join MASTER UrMaster on MASTER.Vorgangursprung = UrMaster.Vorgangsnummer
where (UrMaster.referenznr = 'ABT_25' )

Das dürfte aber zu einem vollständig anderen Ergebnis führen, da die Abfrage auf die ReferenzNr ja nur ein Teil innerhalb der letzten AND-Bedingung ist. Diese Bedingung wird ja nur auf eine bereits erstellte Teilmenge angewandt und nicht auf die Ursprungstabelle. Von daher könnte ich mir vorstellen, dass dort die Nutzung des Index für die Datenbank nicht mehr möglich ist.

Eventuell könnte es aber hilfreich sein, im zweiten Left-Join grundsätzlich auf UrMaster.referenznr <> 'ABT_25' einzuschränken und in einem dritten Left-Join nur die Besonderheiten von UrMaster.referenznr = 'ABT_25' "abzuarbeiten".

p80286 23. Jun 2016 10:30

AW: SQL Sauert zu lange
 
Wenn man die Datenbank kennen würde, könnte man viel mehr dazu sagen. z.b. diese
SQL-Code:
Slave.ZusatzStatus= or Slave.Zusatzstatus=
Orgie, könnte die nicht durch
SQL-Code:
Slave.ZusatzStatus<>x and Slave.Zusatzstatus<>y
ersetzt werden?
U.U. kann man 'ABT_25' auch durch eine liste von IDs ersetzen (anderer Index)?
Und dieses
Code:
 SLAVE.SlaveStatus = 'In Arbeit' and SLAVE.Dzusatz is NULL) or
      (SLAVE.SlaveStatus = 'In Abreit' and SLAVE.Dzusatz = 'Gesperrt'
würde ich durch
SQL-Code:
SLAVE.SlaveStatus = 'In Arbeit' and (SLAVE.Dzusatz is NULL or SLAVE.Dzusatz = 'Gesperrt')
ersetzen.

Gruß
K-H


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:21 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz