![]() |
Datenbank: Firebird • Version: 2.5. • Zugriff über: IBDAC
Performancefrage
Hallo,
ich habe eine Tabelle Messungen in der sind verschiedene Informationen zu Messungen abgelegt :-) Unter anderem auch der Startzeitpunkt als TIMESTAMP. Wenn ich jetzt die jüngste Messung haben möchte würde ich folgenden Select machen:
Code:
Über den PrimeryKey ID: Integer kann ich nicht gehen, da die Messungen nicht zwingend chronologisch in der Datenbank abgelegt werden.
SELECT bla, blub, tralla FROM Messungen WHERE Startzeit = (select MAX(Startzeit) from Messungen);
So, jetzt meine Fragen:
Danke, Chris P.S.: Gibt es eigentlich keine SQL-Tags? |
AW: Performancefrage
SQL-Code:
Hierfür am Besten noche einen Index auf der Spalte Startzeit
SELECT bla, blub, tralla FROM Messungen WHERE Startzeit = ( select first 1 startzeit from Messungen order by startzeit desc);
BTW. SQL-Formatierung geht als Erweiterung des CODE-Tags (=SQL) |
AW: Performancefrage
Hi Chris,
Sub-Selects sind IMHO nicht so performant wie andere Lösungen. Man sollte möglichst auf die verzichten. Deine Abfrage würde ich wie folgt umschreiben:
Code:
Ohne einen Index muss sowohl für "MAX(Startzeit)" als auch für "ORDER BY Startzeit DESC" die gesamte Tabelle gescannt werden. Die DB kann da keine Optimierungen vornehmen.
SELECT FIRST 1 bla, blub, tralla FROM Messungen ORDER BY Startzeit DESC
Dieser Fall schreit förmlich nach einem Index...kommt natürlich auf die Größe der Tabelle an. |
AW: Performancefrage
Dabei ist es wichtig, dass ein absteigender Index angelegt wird. :-D
|
AW: Performancefrage
Zitat:
Zitat:
Zitat:
Gruß, Chris |
AW: Performancefrage
Richtig.
MIN => aufsteigender (ASC) Index MAX => absteigender (DESC) Index Thomas |
AW: Performancefrage
Danke Euch allen :-)
Ich werde also zwei Indizes anlegen und die Variante
SQL-Code:
bzw
SELECT FIRST 1 bla, blub, tralla FROM Messungen ORDER BY Startzeit DESC
SQL-Code:
verwenden.
...ASC
Bleibt nur noch die Frage ob man noch noch schneller bekommt mit einer SP? Gruß, Chris |
AW: Performancefrage
Zitat:
Fazit: Das lohnt sich nicht. |
AW: Performancefrage
Zitat:
Gruß, Chris |
AW: Performancefrage
Zitat:
|
AW: Performancefrage
Echt. :-D
Probier einfach mal aus: Erstelle dir eine Tabelle mit einem Feld und führe dann aus: - MIN und MAX ohne Index - MIN und MAX bei Existenz eines aufsteigenden Index - MIN und MAX bei Existenz eines absteigenden Index - MIN und MAX bei Existenz beider Indizes Welche Ausführungspläne werden für die 4 Varianten gewählt? |
AW: Performancefrage
Ach, ich sehe gerade: Firebird. Na dann is klar.
MSSQL z.B. ist das schlauer |
AW: Performancefrage
Was hat das mit schlauer zu tun? Wenn ich z.B. eine absteigend sortierte Zahlenliste habe und möchte den kleinsten Wert ermitteln, muss ich die gesamte Liste durchlaufen, da er ja logischerweise ganz am Ende steht. Brauche ich den größten Wert, bekomme ich den quasi sofort. Genauso verhält es sich natürlich äquivalent andersherum.
|
AW: Performancefrage
Die Sache ist die, dass Firebird keine bidirektionalen Indizes unterstützt, d.h. eine rasche Travesierung von vorne nach hinten und umgekehrt mit nur einem Index.
|
AW: Performancefrage
Wenn ich mir die SQL-Abfrage von ChristE ansehe, kann die eigentlich nicht funktionieren:
SELECT bla, blub, tralla FROM Messungen WHERE Startzeit = (select MAX(Startzeit) from Messungen) MAX ist in der WHERE-Klausel nicht erlaubt. Würde folgendes vorschlagen:
Code:
Das for select braucht man, da mehrere Datensätze zurückgeliefert werden könnten. Will man nur einen Datensatz, kann man z.B. noch eine Abfrage nach der max(ID) zwischenschalten und die dann in der letzten where-Klausel benutzen.
SET TERM ^ ;
CREATE OR ALTER PROCEDURE TESTP returns ( pdatum timestamp, pWert integer) as declare variable adatum timestamp; begin /* Procedure Text */ select max(datum) from Messungen into :adatum; for select datum, wert from Messungen where datum = :adatum into :pdatum ,:pwert do suspend; end^ SET TERM ; ^ Ein Test mit IBExpert und rund 19000 Datensätzen sowie 5 Ergebniszeilen dauert weniger als eine halbe Sekunde, das Ergebnis ist praktisch sofort da. |
AW: Performancefrage
Wo steht denn MAX in der WHERE-Klausel? Das MAX gehört zum Subselect und ist dort durchaus erlaubt.
|
AW: Performancefrage
Sonst müsste es in die HAVING-Klausel
|
AW: Performancefrage
@Ralf: MAX ist im Subselect und durchaus erlaubt. Bzgl. Performance. 19.000 Datensätze würde ich nicht für Performancemessungen hernehmen. Das sind Peanuts. Interessanter wirds im Millionenbereich.
|
AW: Performancefrage
Ja stimmt, hab es noch mal probiert. Beim 1. Versuch hat IBExpert das angemeckert. Scheint aber etwas langsamer zu sein als die SP, eine genaue Messung habe ich leider nicht.
Mit 850000 Datensätzen komme ich mit beiden Varianten auf rund 5 s. |
AW: Performancefrage
Ich nehme mal an, ohne Indizes?
|
AW: Performancefrage
Richtig, auf Datum ist kein Index gewesen. Mit Index etwa die halbe Zeit.
|
AW: Performancefrage
Ok, dann wieder etwas zurück im Thread. Hast auch einen absteigenden Index angelegt, weil sonst muss er beim MAX(...) einen Full-Table-Scan machen.
|
AW: Performancefrage
@ChrisE: Da Firebird 2.5 eingesetzt wird, kann man natürlich auch die Trace API dazu verwenden, um Flaschenhälse rauszufinden. Siehe auch folgendes Video:
![]() |
AW: Performancefrage
Mit descending wird es noch schneller, dann weniger als 1 s
|
AW: Performancefrage
Zitat:
Zitat:
Gruß, Chris |
Alle Zeitangaben in WEZ +1. Es ist jetzt 19:17 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz