Datenbank: Firebird • Version: 2.1 • Zugriff über: IBConsole
ORDER in Unterselect sehr langsam
Hallo, ich verwende folgendes Statemant
SQL-Code:
als Plan bekomme ich folgendes raus
SELECT P.ID, (SELECT FIRST 1 TB.AUFTRAGID FROM TERMINAL_BUCHUNGEN TB WHERE TB.PERSONALID = P.ID ORDER BY TB.BUCHUNG DESC) AS AUFTRAGID
FROM PERSONAL P
Code:
würde eigetnlich gut aussehen, aber leider ist es sehr langsam (5 Sekunden)
PLAN (TB ORDER TB_BUCHUNG INDEX (TB_PERSONALID))
PLAN (P NATURAL) im vergleich ohne dem ORDER
SQL-Code:
als PLAN
SELECT P.ID, (SELECT FIRST 1 TB.AUFTRAGID FROM TERMINAL_BUCHUNGEN TB WHERE TB.PERSONALID = P.ID) AS AUFTRAGID
FROM PERSONAL P
Code:
und benötigt ca. 100 ms
PLAN (TB INDEX (TB_PERSONALID))
PLAN (P NATURAL) das problem ist, das ich dieses statemant sehr oft aufrufen muß, ... und dadurch macht sich diese 5 sekunden sehr bemerkbar :( weiss jemand wie ich das beschleunigen kann? |
Re: ORDER in Unterselect sehr langsam
Zitat:
|
Re: ORDER in Unterselect sehr langsam
Liste der Anhänge anzeigen (Anzahl: 1)
ja ist
habe es im ORDER auch mit TB.ID prboiert, das ist der PRIMARY KEY und auch bei dem ist es gleich langsam da bekomme ich folgenden PLAN
Code:
PLAN (TB ORDER RDB$PRIMARY87 INDEX (TB_PERSONALID))
PLAN (P NATURAL) |
Re: ORDER in Unterselect sehr langsam
Hallo
Du kannst ja beim Select den Plan mit angeben ==> Vielleicht wirds dadurch schneller mfg Reinhold ----------- Dokumentation der Arzneimittel www.ithof.de |
Re: ORDER in Unterselect sehr langsam
Zitat:
bzw. gibt es irgendwoi eine doku, wann FB für einen ORDER einen Index verwendet und wann nicht?!?!? |
Re: ORDER in Unterselect sehr langsam
Hallo
Sorry hab deine Meldung nochmals genau gelesen. Ich dachte der Plan der 100 ms Lösung könntest du verwenden, der ist jedoch ohne Order by ... Als nächstes würde ich eine View mit eben der aktuellsten Auftragsid pro Buchung testen. ==> Wenn das auch nichts hift könnte man noch die Daten (aktuelle Auftragsid pro Buchung) in eine Hilfstabelle schreiben. Klar wiederspricht der Grundregel keine berechenbaren Daten speichern, aber schnell wird das auf alle Fälle. mfg Reinhold |
Re: ORDER in Unterselect sehr langsam
Zitat:
Ich hätte auch schon probiert die SELECT in SELECT in eine plain SELECT (also mit Joins umzubauen) aber das bringe ich auch irgendwie nicht zusammen Den soviel ich bisher merken konnte hat der Firebird noch oft probleme, so wie mit dem IN ... :( |
Re: ORDER in Unterselect sehr langsam
Hallo,
Zitat:
SQL-Code:
Was willst du denn eigentlich erreichen ?
SELECT P.ID, (SELECT FIRST 1 TB.AUFTRAGID FROM TERMINAL_BUCHUNGEN TB WHERE TB.PERSONALID = P.ID ORDER BY TB.BUCHUNG DESC) AS AUFTRAGID
FROM PERSONAL P Hast du auf TERMINAL_BUCHUNGEN.BUCHUNG auch einen DESC Index ? Ein normaler (ASC) reicht nicht. Ich würde das SubSelect eh weglassen. Wie du richtig festgestellt hast, at FB du schon noch Probleme. Mach es doch etwa so
SQL-Code:
Grouping ist meine grosse Schwäche ;)
Select Max(TB.BUCHUNG) AS AUFTRAGID, PersonalId
From FROM TERMINAL_BUCHUNGEN Group By PersonalId Ob dann noch ein Desc Index auf TERMINAL_BUCHUNGEN.BUCHUNG notwendig ist, musst du ausprobieren. Auf TERMINAL_BUCHUNGEN.PERSONALID sollte aber einer draufsein. Heiko |
Re: ORDER in Unterselect sehr langsam
Zitat:
Hallo also ich habe mittlerweile auf fast jedes Feld 2 Indexe einen ASC und einen DESC (zum testen) Die tabelle hat ja auch mittlerweile schon über 8 Millionen einträge ... Das Problem ist ja, eine normales Group bringt nicht die werte die ich brauche, da ich ja den Wert AUFTRAGID aus der Tabelle TERMINAL_BUCHUNGEN brauche der am aktuellesten ist (sprich TB.BUCHUNG am ältesten) (in der echt applikation sind noch ein paar WHERE dabei, aber die machen keinen Unterschied aus) wenn eis ein SELECT (TBAUFTRAGID BY MAX(TB.BUCHUNG)) oder so geben würde sprich eine Aggreagatfunktion, die mir die Spalte AuftragID zurückliefert, von der Zeile, wo MAX(TB.BUCHUNG) das wäre ideal .... sowas kann ich meines erachtens nur mit so nem (SELECT FIRST 1 ... ) erreichen, ansonsten würde ich es auch in ein GROUP umbauen ... |
Re: ORDER in Unterselect sehr langsam
Hallo,
das hatte ich BUCHUNG, AUFTRAGID in der Struktur übersehen. Naja, zur Not ne SP erzeugen. Auf jeden Fall ist die Tabelle Personal unnötig, da die PersonalId ja schon in der Tabelle TERMINAL_BUCHUNGEN steht. Heiko |
Re: ORDER in Unterselect sehr langsam
Zitat:
Man kann es auch mal so probieren:
SQL-Code:
Ungetestet natürlich...
select p.id
, (select tb.auftragid from terminal_buchungen tb where tb.personalid = p.id and tb.buchung = (select max(tbs.buchung) from terminal_buchungen tbs where tbs.personal_id = p.id) ) as auftragid from personal p Das Feld Buchung muss dann natürlich eindeutig sein, sonst: multiple rows in singleton select... [EDIT]für das max muss auch das Feld buchung einen desc Index haben[/EDIT] Frank |
Re: ORDER in Unterselect sehr langsam
Hallo,
versuche das mal
SQL-Code:
Ansonsten solltest du mal das SQL-Script der Tabellen
select p1.id, TB1.auftragsid
from personal p1 join TERMINAL_BUCHUNGEN TB1 on TB1.pid=p1.id where tb1.buchung in (select max(tb2.buchung) from TERMINAL_BUCHUNGEN where (tb2.pid=p1.id) and (tb2.auftragsis=tb1.auftragsid)); + ein paar Daten liefern. Habe keine Lust, das selber zu tippern. Heiko |
Re: ORDER in Unterselect sehr langsam
also das
SQL-Code:
verwendet
select p.id
, (select tb.auftragid from terminal_buchungen tb where tb.personalid = p.id and tb.buchung = (select max(tbs.buchung) from terminal_buchungen tbs where tbs.personalid = p.id) ) as auftragid from personal p
Code:
also verwendet alle Indexe, braucht aber nun fast 9 sekunden
PLAN (TBS ORDER TERMINAL_BUCHUNGEN_BUCHUNG INDEX (TB_PERSONALID))
PLAN (TB INDEX (TB_BUCHUNG)) PLAN (P NATURAL) dieses Command
SQL-Code:
verwendet PLAN
select p1.id, TB1.auftragid
from personal p1 join TERMINAL_BUCHUNGEN TB1 on TB1.personalid=p1.id where tb1.buchung in (select max(tb2.buchung) from TERMINAL_BUCHUNGEN tb2 where (tb2.personalid=p1.id) and (tb2.auftragid=tb1.auftragid));
Code:
braucht aber fast 14 Minuten ...
PLAN (TB2 ORDER TERMINAL_BUCHUNGEN_BUCHUNG INDEX (TB_PERSONALID, TB_AUFTRAGID))
PLAN JOIN (P1 NATURAL, TB1 INDEX (TB_PERSONALID)) ich habe mal folgendes probiert
SQL-Code:
das braucht "nur" mehr 1.5 sekunden, also immer noch nicht wirklich schnell.
set term #;
execute block returns (ID INTEGER, MBID INTEGER) as declare variable ID1 INTEGER; begin for execute statement 'select ID FROM PERSONAL' into ID1 DO begin ID = ID1; MBID = null; execute statement 'SELECT FIRST 1 TB.AUFTRAGID FROM TERMINAL_BUCHUNGEN TB WHERE TB.PERSONALID = ' || ID || ' ORDER BY TB.BUCHUNG DESC' INTO MBID; suspend; end end # set term ;#
Code:
Kann es sein, das es nicht mehr schneller geht diese Abfrage?
select count(*) from personal -> 268
select count(*) from Terminal_Buchungen -> 321937 |
Re: ORDER in Unterselect sehr langsam
Habe mal folgendes probiert :
SQL-Code:
wobei ich beim PErsonalID un auf verscheiden filtere ...
set term #;
execute block as declare variable ID1 INTEGER; declare I int = 0; begin while (i < 100) do begin execute statement 'SELECT FIRST 1 TB.AUFTRAGID FROM TERMINAL_BUCHUNGEN TB WHERE TB.PERSONALID = 9 ORDER BY TB.BUCHUNG DESC' INTO ID1; i = i + 1; end end # set term ;#
Code:
Wie hängt das da zusammen?, je wenige einträge ein personal hat, desto länger dauert die abfrage?!?!?!?!?!
PersonalID=9 -> 2.4 Sekunden (SELECT count(*) FROM TERMINAL_BUCHUNGEN TB WHERE TB.PERSONALID = 9 -> 3 Einträge)
PersonalID=2 -> 20 ms (SELECT count(*) FROM TERMINAL_BUCHUNGEN TB WHERE TB.PERSONALID = 2 -> 400 Einträge) PersonalID=20 -> 20 ms (SELECT count(*) FROM TERMINAL_BUCHUNGEN TB WHERE TB.PERSONALID = 20 -> 6000 Einträge) PersonalID=60 -> 2.4 Sekunden (SELECT count(*) FROM TERMINAL_BUCHUNGEN TB WHERE TB.PERSONALID = 60 -> 4 Einträge) Ich verstehe das absolut nicht mehr |
Re: ORDER in Unterselect sehr langsam
Versuchs mal so:
SQL-Code:
select distinct personal.id as personalid, max(terminal_buchungen.auftragid) as auftragid
from terminal_buchungen inner join personal on personal.id = terminal_buchungen.personalid group by personalid |
Re: ORDER in Unterselect sehr langsam
Zitat:
Ich brauche nicht den größten AuftragID wert sondern den AuftragID Wert von dem datensatz, wo Buchugn am größten ist ... |
Re: ORDER in Unterselect sehr langsam
Zitat:
SQL-Code:
select distinct personal.id as personalid, terminal_buchungen.auftragid as auftragid, max(terminal_buchungen.buchung) as letzte_buchung
from terminal_buchungen inner join personal on personal.id = terminal_buchungen.personalid group by personalid, auftragid |
Re: ORDER in Unterselect sehr langsam
Leider ist deine Frage nicht ganz präzise formuliert...
Was ist wenn einer Person noch gar kein Auftrag zugewiesen wurde, soll diese dann trotzdem erscheinen mit einem NULL Wert oder nicht? Falls ja, versuch es so...
SQL-Code:
Eventuell auch etwas kompackter...
SELECT p.id, tb.auftragid
FROM personal p LEFT JOIN (SELECT personalid, auftragid FROM terminal_buchungen tb WHERE buchung = (SELECT MAX(buchung) FROM terminal_buchungen WHERE auftragid = tb.auftragid)) tb ON p.id = tb.personalid
SQL-Code:
Falls nein, versuch es so...
SELECT p.id, tb.auftragid
FROM personal p LEFT JOIN terminal_buchungen tb ON p.id = tb.personalid AND (SELECT MAX(buchung) FROM terminal_buchungen WHERE auftragid = tb.auftragid) = tb.buchung
SQL-Code:
SELECT p.id, tb.auftragid
FROM personal p INNER JOIN terminal_buchungen tb ON p.id = tb.personalid WHERE buchung = (SELECT MAX(buchung) FROM terminal_buchungen WHERE auftragid = tb.auftragid) |
Re: ORDER in Unterselect sehr langsam
Hallo,
warum verwendest du in der SP überhaupt eine Execute Statement ???
SQL-Code:
for select personal.id into :PId do
begin select xxx into :AuftragsId end; Wo wir beim Plan sind. Was kommt als Plan bei, oder anders gefragt: Hat TB.BUCHUNG wirklich einen Desc Index ?
SQL-Code:
SELECT FIRST 1 TB.AUFTRAGID FROM TERMINAL_BUCHUNGEN TB
WHERE TB.PERSONALID = 1 ORDER BY TB.BUCHUNG DESC Heiko [edit=mkinzler]SQL-Tags eingefügt Mfg, mkinzler[/edit] |
Re: ORDER in Unterselect sehr langsam
Man sollte dann aber ein suspend einfügen
|
Re: ORDER in Unterselect sehr langsam
@webcss: Das liefert auch die falschen daten
Ich brauche eine Liste von Personal, und zusätzlich brauche ich zu jedem Personal den Auftrag, den er zuletzt gestempelt hat (die letzte Stempelung ist jene, wo BUCHUNG am größten ist)
SQL-Code:
so funktioniert das aber nicht?
for execute statement
'select ID FROM PERSONAL' into ID1 DO begin ID = ID1; MBID = null; SELECT FIRST 1 TB.AUFTRAGID FROM TERMINAL_BUCHUNGEN TB WHERE TB.PERSONALID = ID INTO MBID; suspend; end so auch nicht
SQL-Code:
wie kann ich da das Where aufbauen?
SELECT FIRST 1 TB.AUFTRAGID FROM TERMINAL_BUCHUNGEN TB WHERE TB.PERSONALID = :ID INTO MBID;
@hoika ja TB.Buchung hat beide Indexe (hatte einen Screenshott von IBConsole drauf) @omata: es ist mal egal ob die Personal ohne aufträge angezeigt werden oder nicht nur die 1te Abfrage dauert ca 4Minuten (und liefert irgendwie komische daten ;) ) die 2te dauert auch ca 4min die 3te dauert auch ca. 4min |
Re: ORDER in Unterselect sehr langsam
Hallo,
SQL-Code:
Was kommt denn für eine Fehlermeldung ?
for select ID FROM PERSONAL into ID1
DO begin ID = ID1; MBID = null; SELECT FIRST 1 TB.AUFTRAGID FROM TERMINAL_BUCHUNGEN TB WHERE TB.PERSONALID = ID order by TB.Buchung Desc //// das hatte noch gefehlt INTO MBID; suspend; end Wenn er wegen einer Variablen meckert, immer ein : davor ;) Zum Arbeiten empfehle ich IBExpert (gibt es auch als kostenlose Personal) Heiko |
Re: ORDER in Unterselect sehr langsam
Zitat:
hmmm, also bei dem hier, kommen flasche daten raus (er lädt gar nix rein .... )
SQL-Code:
und bei dem
SELECT FIRST 1 TB.AUFTRAGID FROM TERMINAL_BUCHUNGEN TB WHERE TB.PERSONALID = ID INTO MBID;
SQL-Code:
kommt ein Fehler wegen dem ":"
SELECT FIRST 1 TB.AUFTRAGID FROM TERMINAL_BUCHUNGEN TB WHERE TB.PERSONALID = :ID INTO MBID;
Code:
Dynamic SQL Error
SQL error code = -901 undefined message number |
Re: ORDER in Unterselect sehr langsam
Hallo,
zeige doch nch mal den kompletten Quellcodce der SP. Message-Number: Kann es sein, dass du mehrere Firebird-Installationen auf deinem Rechner hast ? Der scheint in der falschen firebird.msg zu suchen. Heiko |
Re: ORDER in Unterselect sehr langsam
Bzw scheint der Client nicht zum Server zu passen.
|
Re: ORDER in Unterselect sehr langsam
oh, ja, der client passt nicht zum server, ist ne alte IBConsole ...
SQL-Code:
Das ist die SP, wobei es sich nur am :ID Parameter spiesst, habe statt dem auch ID1 probiert, geht auch nicht
set term #;
execute block returns (ID INTEGER, MBID INTEGER) as declare variable ID1 INTEGER; begin for execute statement 'select ID FROM PERSONAL' into ID1 DO begin ID = ID1; MBID = null; SELECT FIRST 1 TB.AUFTRAGID FROM TERMINAL_BUCHUNGEN TB WHERE TB.PERSONALID = :ID INTO MBID; suspend; end end # set term ;#
SQL-Code:
wenn ichs so verwende, dann meckert er, das er ID1 nicht kennt
SELECT FIRST 1 TB.AUFTRAGID FROM TERMINAL_BUCHUNGEN TB WHERE TB.PERSONALID = ID1 INTO MBID;
wenn ichs so verwende
SQL-Code:
dann läuft es durch, aber verwendet natrülich das Feld ID von TERMINAL_BUCHUNGEN, und läuft deshalb falsch ...
SELECT FIRST 1 TB.AUFTRAGID FROM TERMINAL_BUCHUNGEN TB WHERE TB.PERSONALID = ID INTO MBID;
|
Re: ORDER in Unterselect sehr langsam
Müsste dann auch
SQL-Code:
heissen
SELECT FIRST 1 TB.AUFTRAGID FROM TERMINAL_BUCHUNGEN TB WHERE TB.PERSONALID = :ID1 INTO :MBID;
|
Re: ORDER in Unterselect sehr langsam
Hallo,
@Gruber_Hans_12345 momentan begreife ich nicht ganz, was Du möchtest: Dein erstes Select sieht für mich so aus: Gesucht wird der erste Satz, bei absteigender Sortierung nach BUCHUNG, aus der Tabelle TERMINAL_BUCHUNGEN, zu dem PERSONALID mit der ID aus der Tabelle PERSONAL übereinstimmt. Das dürfte dann doch eigentlich sowas sein:
SQL-Code:
oder liege ich da falsch?
select FIRST 1 P.ID, TB.AUFTRAGID, TB.BUCHUNG
from PERSONAL P, TERMINAL_BUCHUNGEN TB where P.ID = TB.PERSONAL_ID ORDER BY TB.BUCHUNG DESC |
Re: ORDER in Unterselect sehr langsam
Hallo,
lade dir doch endlich mal IBExpert runter, Mensch !!! ;)
SQL-Code:
execute block
set term #;
execute block returns (ID INTEGER, MBID INTEGER) as declare variable ID1 INTEGER; begin for execute statement 'select ID FROM PERSONAL' into ID1 DO begin ID = ID1; MBID = null; SELECT FIRST 1 TB.AUFTRAGID FROM TERMINAL_BUCHUNGEN TB WHERE TB.PERSONALID = :ID INTO MBID; suspend; end end # set term ;# was zum Teufel ist das denn ??? OK, ich weiss, was es ist ;) Aber das hat hier nichts zu suchen.
SQL-Code:
wo ist das order by buchung desc ?
SELECT FIRST 1 TB.AUFTRAGID FROM TERMINAL_BUCHUNGEN TB WHERE TB.PERSONALID = :ID INTO MBID;
Vorschlag
SQL-Code:
CREATE PROCEDURE SP_Bla
RETURNS ( ID INTEGER, MBID INTEGER) AS begin for select ID FROM PERSONAL into :ID DO begin MBID = null; SELECT FIRST 1 TB.AUFTRAGID FROM TERMINAL_BUCHUNGEN TB WHERE TB.PERSONALID = ID order by tb.buchung desc INTO :MBID suspend; end end Heiko [edit=mkinzler]SQL-Code in SQL-Tags gepackt Mfg, mkinzler[/edit] |
Re: ORDER in Unterselect sehr langsam
@hoika
mach ich dann gleich :) oh, stimmt das order by viel weg ... das problem bei deiner SQL ist, das er beim WHERE TB.PERSONALID = ID, nicht den ID von den variablen her nimmt, sondern den von TB ... |
Re: ORDER in Unterselect sehr langsam
also hab mir das IBExpert runtergeladen
da funkt das nun
SQL-Code:
Allerdings sehe ich in der PErsonal keine infos über die Zeiten und co, so wie in der IBConsole ....
execute block
returns (ID INTEGER, MBID INTEGER) as declare variable ID1 INTEGER; begin for select ID FROM PERSONAL into :ID DO begin MBID = null; SELECT FIRST 1 TB.AUFTRAGID FROM TERMINAL_BUCHUNGEN TB WHERE TB.PERSONALID = :ID INTO :mbid; suspend; end end |
Re: ORDER in Unterselect sehr langsam
Hi,
versuch mal folgendes:
SQL-Code:
Ich hoffe, ich habe mich nirgends mit den Namen vertan.
SELECT P.ID, TEMP.BUCHUNG, TB.AUFTRAGID FROM PERSONAL P
JOIN (SELECT PERSONALID, MAX(BUCHUNG) BUCHUNG FROM TERMINAL_BUCHUNGEN GROUP BY PERSONALID) TEMP on TEMP.PERSONALID=P.ID JOIN TERMINAL_BUCHUNGEN TB ON TEMP.BUCHUNG = TB.BUCHUNG Grüße |
Re: ORDER in Unterselect sehr langsam
Hallo,
stimmt ;) Deshalb schreibe ich sowas auch immer so
SQL-Code:
Oder Unterstriche, halt immer was eindeutiges.
CREATE PROCEDURE SP_Bla
RETURNS ( theID INTEGER, theMBID INTEGER) AS begin for select ID FROM PERSONAL into :theID DO begin MBID = null; SELECT FIRST 1 TB.AUFTRAGID FROM TERMINAL_BUCHUNGEN TB WHERE TB.PERSONALID = theID order by tb.buchung desc INTO :theMBID suspend; end end Heiko |
Re: ORDER in Unterselect sehr langsam
Zitat:
funktionieren tut es nun ja, nur in der Personal Edition gibt es leider keine PLAN oder PERFORMANCE Daten, sehe nun nicht ob ich schneller bin oder nicht ... |
Re: ORDER in Unterselect sehr langsam
Also der Plan wird bei mir angezeigt
|
Re: ORDER in Unterselect sehr langsam
ja, der PLAN schon :
SQL-Code:
execute block
returns (ID INTEGER, MBID INTEGER) as declare variable ID1 INTEGER; begin for select ID FROM PERSONAL into :ID DO begin MBID = null; SELECT FIRST 1 TB.AUFTRAGID FROM TERMINAL_BUCHUNGEN TB WHERE TB.PERSONALID = :ID INTO :mbid; suspend; end end Statement Plan -------------- PLAN (TB INDEX (TB_PERSONALID)) PLAN (PERSONAL NATURAL) |
Re: ORDER in Unterselect sehr langsam
Hat PERSONAL keinen PK bzw ist es ein anderer als ID?
|
Re: ORDER in Unterselect sehr langsam
Doch aht es und ist auch der ID
meinst du wegen dem PLAN (PERSONAL NATURAL) ? Ich vermute mal das ist, weil ich die ganze PERSONAL Tabelle auslese, daher kann bzw brauche ich ja keinen Index in dem Fall oder? |
Re: ORDER in Unterselect sehr langsam
Könnte sein
|
Re: ORDER in Unterselect sehr langsam
Versuch mal einfach folgendes:
SQL-Code:
:wink:
SELECT Terminal_Buchungen.PersonalID, Max(Terminal_Buchungen.AuftragID), Max(Terminal_Buchungen.Buchung)
FROM Terminal_Buchungen GROUP BY PersonalID |
Alle Zeitangaben in WEZ +1. Es ist jetzt 01:09 Uhr. |
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