Exists oder inner join


#1

Hallo zusammen,
ich habe in meinem Programm ein ziemliches Performance-Problem!

Mehrere Abfragen zusammen dauern 14 Sekunden, das muss ich beheben.

Gleich mal vorweg warum ich nicht selber mit Time-millisekunden teste was schneller ist:
Ich habe 100 Stellen von dem ähnlichen Code, diese überall mal auszutauschen um dann nur mal TESTEN zu können, würde einen immensen Zeit und Kostenbedarf erfordern.

Hier meine SQL Query:
[SQL]select count(*) from tanz where alt='Junioren II (15,6 - 19,5 J.)'
and exists (select * from punkte where tanz.TANZID = punkte.TID)[/SQL]

So kurze Erklärung:
Ich hole mir die Anzahl von Tänzen aus der Tabelle “tanz” wo die Altersklasse “Junioren 2 (…)” drinnen steht. Dieser Tanz muss aber schon Punkte haben, damit er im count(*) aufgenommen werden darf.
Deswegen schreibe ich exists(alles von Punkte wo die Tanzid gleich der PunkteTanzID ist.

Sollte ich das exists jetzt austauschen zu einem InnerJoin?
Würde dann die Query schneller laufen?

Danke sehr


#2

Ich verstehe den Sinn dahinter nicht. COUNT(*) liefert doch eine Null zurück, wenn die Tabelle leer ist. Weshalb ist das problematisch?
Und wenn die Zeile mit einer Null nicht ausgegeben werden darf, dann kannst du sie einfach wegfiltern (eine HAVING-Klausel sollte es wohl möglich machen :wink: )


#3

Okay genauerere Erklärung, denn dass mir count null zurück gibt ist bei mir gar nicht möglich.

1.Tabelle Tanz(Columnname mit Werte):
Tanzid | Tanzname | alt
1 | Tanz1 | Kinder
2 | Tanz2 | Junioren II (15,6 - 19,5 J.)
3 | Tanz3 | Kinder
4 | Tanz4 | Kinder
5 | Tanz5 | Junioren II (15,6 - 19,5 J.)
usw. (Ca. 900 Einträge)

2.Tabelle Punkte
PunkteID | TID | Technik | Level
1 | 1 | 9 | 66
2 | 3 | 20 | 40
3 | 4 | 22 | 33
4 | 5 | 32 | 55
usw.
Wichtig dabei ist, dass nicht jeder Tanz in der Tabelle Tanz eine zugehörige Punkte.TID hat.
z.B. Tanz 2 hat keine Punkte.

Jetzt möchte ich mit meiner Query alle Tänze haben, die die altersklasse (alt) Junioren II (15,6 - 19,5 J.) UND einen Eintrag in der Tabelle Punkte haben.

Wenn wir das obrige Beispiel jetzt hernehmen würde (mit maximal 5 Tänzen) würde mir die Query 1 zurück liefern, denn der Tanz2 ist nicht bewertet und wird deshalb auch nicht bei count(*) dazugezählt.

So hoffe jetzt ist es verständlicher, sonst bemüh ich mich gern nochmal :wink:


#4

So mal als Bitfummler eine Anmerkung:
Der Stringvergleich kostet sehr viel Zeit.
Wie wäre es mit einer extra Tabelle, in denen es eine Zuordnung von alt zu einer Zahl gibt?

[SQL]
ID Altersbereich
1 "Kind"
2 "Junioren II (15,6 - 19,5 J.)"
3 “Mittelalter (20-40)”

9 “Oppa/Oma”
[/SQL]

[SQL]where alt = 2…[/SQL]


#5

Gibt es einen [SQL]FOREIGN KEY CONSTRAINT[/SQL] zwischen Tanz.TID und Punkte.TID?

bye
TT


#6

Ich schrieb eine Null, damit meinte ich eine 0 :wink:

Ok, jetzt habe ich verstanden, was du machen möchtest.
Ich glaube nicht, dass es eine Schande wäre, wenn du etwas Redundanz schaffst, um die Performance zu erhöhen. Will meinen, dass du in der Tanz-Tabelle einfach eine Spalte “wurde bewertet” hinzufügst.

Allerdings wäre es wahrscheinlich sinnvoll, wenn du prinzipiell die Datenbank mal profilen lassen würdest, welche Queries wie lange brauchen.

Ich weiß nicht, welche DB du benutzt, aber ggf. ist serverseitiges Profiling angebracht. Falls du MySQL benutzt, hilft dir das Performance Schema weiter.

Um spezielle Queries etwas besser zu verstehen, hilft dir das EXPLAIN-Statement.


#7

So danke an alle mal für eure Antworten!

[MENTION=1599]MZ80A[/MENTION]
Das habe ich noch vor, aber nicht aus Performancegründen
PS: Ich glaube Stringvergleich würde bei meinen 900Datensätzen auch nur ca. 30 Millisekunden bringen. Aber immer mehr Performance :wink:

[MENTION=1566]Timothy_Truckle[/MENTION]
Nein, könnte man aber machen, bringt das sehr viel und is es dann wieder Sinnvoll, weil das war jetzt ein einfaches Beispiel meiner Datenbank. In Wirklichkeit hat jeder Tanz mehrere PunkteReihen. Das würde heißen eine 1 zu n Beziehung(Tanz zu Punkte).

[MENTION=1561]cmrudolph[/MENTION]
ups, hab gemeint du meintest eine null tut mir leid.

Ok, jetzt habe ich verstanden, was du machen möchtest.
Ich glaube nicht, dass es eine Schande wäre, wenn du etwas Redundanz schaffst, um die Performance zu erhöhen. Will meinen, dass du in der Tanz-Tabelle einfach eine Spalte “wurde bewertet” hinzufügst.

Ja ich glaube ich komm nicht darum rum, das zu machen, wollte zuerst nur nicht meine Datenbank mit sinnlosen Columns überfüllen. Aber ich denke, da kann man sehr wohl ein Auge zudrücken.

Allerdings wäre es wahrscheinlich sinnvoll, wenn du prinzipiell die Datenbank mal profilen lassen würdest, welche Queries wie lange brauchen.

huii da muss ich erst mal googeln was das überhaupt heißt, aber danke für den Tipp, obwohl ich mir sicher bin dass meine MINI-Datenbank (HSQLDB) das sicherlich nicht unterstützt.

Gleiche mit Performance Schema, da muss ich mal in den nächsten Nächten mal reinlesen wie das so funktioniert.

Explain klingt auch sehr interessant, alles überhaupt reichlich nützliche Informationen

Gut ich denke ich habe meine Lösung nun gefunden, ich lasse den Thread bis morgen noch offen, vlt kommt ja noch eine “Gotteserscheinung” oder so ähnlich aber ich danke euch nochmal herzlich
und wünsche nun eine gute Nacht


#8

[QUOTE=Paul279;29882] [MENTION=1566]Timothy_Truckle[/MENTION]
Nein, könnte man aber machen, bringt das sehr viel und is es dann wieder Sinnvoll, weil das war jetzt ein einfaches Beispiel meiner Datenbank. In Wirklichkeit hat jeder Tanz mehrere PunkteReihen. Das würde heißen eine 1 zu n Beziehung(Tanz zu Punkte).[/QUOTE]Gerade dann ist es sinnvoll.
Durch den Constraint wird ein Index angelegt über den der Zugriff auf die Punktetabelle schneller wird.

bye
TT


#9

[QUOTE=Timothy_Truckle;29885]Gerade dann ist es sinnvoll.
Durch den Constraint wird ein Index angelegt über den der Zugriff auf die Punktetabelle schneller wird.[/QUOTE]

Wenn ich ein Schema erzeuge, lege ich prinzipiell überall Foreign Keys an, wo sie logisch hingehören. Und zwar nicht aus Performancegründen, sondern weil dadurch auch die Integrität der Datenbank gewahrt wird (sofern die Datenbank Transaktionen und FKs unterstützt - MyISAM unterstützt sie nicht, man muss bei MySQL die INNODB verwenden).

Mit EXPLAIN werden dir unter anderem Details angezeigt, wie Abfragen, die keinen Index nutzen. Daher kannst du damit ziemlich schnell die Stellen herausfinden, an der die Datenbank etwas länger braucht.

Falls du z. B. einen Spalte “wurde bewertet” hinzufügst, würde dir ein Index auf dieser Spalte auch noch einiges an Performance bringen. Dadurch sparst du dir einen Full-Table-Scan und ersetzt ihn durch einen einfachen Indexzugriff: die Datenbank braucht nichts zu suchen, sondern liest direkt nur die gewünschten Zeilen aus.

Zum Thema MySQL-Performance ist das Buch “High-Performance MySQL” von Baron Schwartz et. al. sehr interessant und umfangreich (wenngleich meine Auflage noch nicht auf das Performance Schema eingeht, weil das Buch einfach schon zu alt ist :wink: ).


#10

Gerade dann ist es sinnvoll.
Durch den Constraint wird ein Index angelegt über den der Zugriff auf die Punktetabelle schneller wird.

Gut, wird gemacht danke sehr

Wenn ich ein Schema erzeuge, lege ich prinzipiell überall Foreign Keys an, wo sie logisch hingehören. Und zwar nicht aus Performancegründen, sondern weil dadurch auch die Integrität der Datenbank gewahrt wird (sofern die Datenbank Transaktionen und FKs unterstützt - MyISAM unterstützt sie nicht, man muss bei MySQL die INNODB verwenden).

Die Daten kommen aus einer Webseitendatenbank mit INNODB, deshalb habe ich in meiner Java-DB keine Foreign-Keys mehr angelegt, weil die Integrität schon gewahrt ist. Das es dadurch schneller ist, ist mir irgendwie auch komplett entfalln. Es wird nachgeholt.

Falls du z. B. einen Spalte “wurde bewertet” hinzufügst, würde dir ein Index auf dieser Spalte auch noch einiges an Performance bringen. Dadurch sparst du dir einen Full-Table-Scan und ersetzt ihn durch einen einfachen Indexzugriff: die Datenbank braucht nichts zu suchen, sondern liest direkt nur die gewünschten Zeilen aus.

Gut, “wurde bewertet” kann ich leider vergessen. Warum werde ich jetzt nicht erklären, aber es geht von meinem Programm her nicht.

Zum Thema MySQL-Performance ist das Buch “High-Performance MySQL” von Baron Schwartz et. al. sehr interessant und umfangreich (wenngleich meine Auflage noch nicht auf das Performance Schema eingeht, weil das Buch einfach schon zu alt ist ).

Das Buch nehm ich gleich mal als Abendlektüre her. “meine Auflage”. Selbst geschrieben oder wie kann man das verstehn :slight_smile:

So, ich geh mal "indexieren"
Danke für die Posts


#11

[QUOTE=Paul279;30020]Das Buch nehm ich gleich mal als Abendlektüre her. “meine Auflage”. Selbst geschrieben oder wie kann man das verstehn :)[/QUOTE]

:smiley:

Ich habe die 2. Auflage, die behandelt MySQL 5.1. Da gab es das Performance Schema noch nicht. Die dritte Auflage behandelt MySQL 5.5 und ich gehe davon aus, dass darin darauf eingegangen wird.