mysql schneller machen
-
Irgendwie hab ich das Gefühl den Mysql Server zu überlasten weil ich zu viele JOINs mache
Und zwar braucht der für folgenden Befehl an die 10 Sekunden:
SELECT tier.tiernummer%10000 AS tiernummer, tier.art FROM kuh LEFT OUTER JOIN pc_tier ON kuh.tiernummer = pc_tier.tiernummer AND kuh.primusnummer = pc_tier.primusnummer JOIN tier ON kuh.tiernummer = tier.tiernummer AND tier.primusnummer = kuh.primusnummer JOIN kuh_rind ON kuh_rind.tiernummer = tier.tiernummer AND kuh_rind.primusnummer = tier.primusnummer JOIN futterdaten AS sorte1 ON sorte1.tiernummer = kuh.tiernummer AND sorte1.primusnummer = kuh.primusnummer AND sorte1.sorte = 0 JOIN futterdaten AS sorte2 ON sorte2.tiernummer = kuh.tiernummer AND sorte2.primusnummer = kuh.primusnummer AND sorte2.sorte = 1 JOIN futterdaten AS sorte3 ON sorte3.tiernummer = kuh.tiernummer AND sorte3.primusnummer = kuh.primusnummer AND sorte3.sorte = 2 JOIN futterdaten AS sorte4 ON sorte4.tiernummer = kuh.tiernummer AND sorte4.primusnummer = kuh.primusnummer AND sorte4.sorte = 3 JOIN milch AS milch_100 ON milch_100.tiernummer = kuh.tiernummer AND milch_100.primusnummer = kuh.primusnummer AND milch_100.tag = 0 JOIN milch AS milch_305 ON milch_305.tiernummer = kuh.tiernummer AND milch_305.primusnummer = kuh.primusnummer AND milch_305.tag = 1 JOIN milch AS milch_gesamt ON milch_gesamt.tiernummer = kuh.tiernummer AND milch_gesamt.primusnummer = kuh.primusnummer AND milch_gesamt.tag = 2 JOIN milch AS milch_leben ON milch_leben.tiernummer = kuh.tiernummer AND milch_leben.primusnummer = kuh.primusnummer AND milch_leben.tag = 3 JOIN gfutterdaten AS gsorte1 ON kuh.primusnummer = gsorte1.primusnummer AND tier.gruppe = gkuh.gruppennummer AND gsorte1.sorte = 0 AND gsorte1.art = 5 JOIN gfutterdaten AS gsorte2 ON kuh.primusnummer = gsorte2.primusnummer AND tier.gruppe = gkuh.gruppennummer AND gsorte2.sorte = 1 AND gsorte2.art = 5 JOIN gfutterdaten AS gsorte3 ON kuh.primusnummer = gsorte3.primusnummer AND tier.gruppe = gkuh.gruppennummer AND gsorte3.sorte = 2 AND gsorte3.art = 5 JOIN gfutterdaten AS gsorte4 ON kuh.primusnummer = gsorte4.primusnummer AND tier.gruppe = gkuh.gruppennummer AND gsorte4.sorte = 3 AND gsorte4.art = 5 JOIN gkuh ON tier.gruppe = gkuh.gruppennummer AND kuh.primusnummer = gkuh.primusnummer JOIN gtier ON tier.gruppe = gtier.gruppennummer AND kuh.primusnummer = gtier.primusnummer AND gtier.art = 5 JOIN gkuh_grind ON tier.gruppe = gkuh_grind.gruppennummer AND kuh.primusnummer = gkuh_grind.primusnummer AND gkuh_grind.art = 5 WHERE 1 AND 1 ORDER BY tier.tiernummer
gibt es da irgendwie eine Möglichkeit das Ding schneller zu machen? Reihenfolge ändern oder Suchindexe oder so?
Also es sind einfach nur ne ganze Menge Tabellen die die jeweils angegebenen Werte oben als Primärschlüssel(tier hat tiernummer und primusnummer usw) haben und dazu noch 1-50 zusätzliche Werte.
-
Mal ne Frage: Bist du sicher, dass du die Datenbank im Vorfeld richtig geplant hast? Bei sowas mögen INDIZES vielleicht helfen, aber so eine Abfrage hab ich noch nie gesehen. Es fehlt einem da ein bisschen die Übersicht, wie ich finde.
Wieviel Einträge hat die DB denn?
-
Ja die is richtig geplant denkich ^^
Zumindest sind die soweit ich das noch aus der Schule weiss sogut wie 100% normalisiert und an den enthaltenen Werten kann ich nix machen, die müssen so sein(ist für eine PC Kopplung an Fütterungsautomaten).Das Prinzip ist das ich Kälber Rinder Kühe und Lämmer habe.
Die kann man an Primusnummer und Tiernummer identifizieren.
Kälber/Lämmer und Kühe/Rinder haben gemeinsame Werte -> kalb_lamm und kuh_rind
Tiere allgemein haben auch gemeinsame werte -> tier
alle Tiere haben identische Futterdaten von 1(lämmer), 2(kälber) und 4(rind/kuh) Futtersorten -> stehen in futterdaten
UND jedes Tier hat eine Gruppe die sich noch einmal genau wie oben aufbaut also gtier, grind_gkuh, gfutterdaten usw.
Dazu kommen dann noch ein paar spezielle Sachen wie Milchwerte bei Kühen usw.Und dadraus brauch ich jetzt einen kompletten Datensatz der alle für eine spezielle Kuh relevanten Daten enthält.
Und viel an Werten drinstehen tut da nicht, sind im Moment in den Tabellen 30 bis 120 Datensätze drin und ich denke mal mehr als 300/1200 wirds nie werden.
-
Da muss ich CarstenJ zustimmen. Nicht so sinnvolle Struktur (Anweisung). Zu viele JOINS verlangsamen die Anweisung (liegt an der Art wie er die Tabellen miteinander verknüpft / vergleicht).
Da aber Beiträge ohne Lösung sinnlos sind, kann ich Dir folgendes empfehlen:
JOIN futterdaten AS sorte1 ON sorte1.tiernummer = kuh.tiernummer AND sorte1.primusnummer = kuh.primusnummer AND sorte1.sorte = 0 JOIN futterdaten AS sorte2 ON sorte2.tiernummer = kuh.tiernummer AND sorte2.primusnummer = kuh.primusnummer AND sorte2.sorte = 1 JOIN futterdaten AS sorte3 ON sorte3.tiernummer = kuh.tiernummer AND sorte3.primusnummer = kuh.primusnummer AND sorte3.sorte = 2 JOIN futterdaten AS sorte4 ON sorte4.tiernummer = kuh.tiernummer AND sorte4.primusnummer = kuh.primusnummer AND sorte4.sorte = 3
Tritt bei Dir mehrmals auf. Warum nicht:
JOIN futterdaten ON futterdaten.tiernummer = kuh.tiernummer AND futterdaten.primusnummer = kuh.primusnummer ... WHERE ((sorte.sorte) = 0) OR ((sorte.sorte) = 1) ...
(Letzteres auch mit IN möglich.)
Ansonsten:
- Bei allen IDs (bei Dir 'Nummern') Indizes setzen.
- Nicht zu viele JOINS! (Vermutlich Dein Hauptproblem)Hoffe inständig in der Eile nichts übersehen. Frage: Was soll das sein? 'WHERE 1 AND 1'. [ 1 AND 1 = 1 ]
-
Also Indizes sind sowieso automatisch gesetzt weil im ON ausschliesslich Primärschlüssel(Also primusnummer, gruppennummer, sorte und tiernummer) benutzt werden.
Hab nochmal von Hand einen Unique Index draufgemacht, hat aber logischerweise nix gebracht.
Und die Struktur der Datenbank.. ich wüsste nicht wie man die ändern sollte das die dann immernoch normalisiert ist.
Ich will halt weder doppelte Einträge noch unnütze Felder(Milch bei Lämmern usw) haben.
Und so wie es jetzt ist ist es ziemlich der einzige Weg das nicht zu haben, zumal das dann genau mit der Klassenstruktur vom dazugehörign C++ Programm übereinstimmt, was auch seine Vorteile mit sich bringt.Und das 1 AND 1 kommt zustande weil ich ein C++ Programm habe das die obige mysqlanweisung dynamisch aus nem haufen Comboboxen/Eingabeboxen usw generiert.
Und ich hab da halt einfach 2 Bedingungen drin die der Benutzer angeben kann.
Macht er dies nicht wird automatisch 1 eingesetzt, daher 1 AND 1 aber denke mal das der mysql den zweiten AND 1 sowieso wegoptimiert.
Aber das ist auch der Grund warum ich am liebsten eine Abfrage hätte wo alles zu Tier XX zurückkommt, weil ich da halt nie so recht weiss welche der 200 Zellen der Benutzer jetzt ausgewählt hat um daraus seine Druckliste/Eingabeliste zu generieren.
Wenns 2-3 Sekunden braucht kein Problem, aber es braucht halt längerIch hab den Feldern jetzt jetzt auch mal Typen gegeben die da besser passten(vorher alles int, jetzt tinyint, smallint usw), die Folge war das der obige mysqlbefehl überhaupt nicht mehr vorm mysql Timeout fertig wird, also das alles noch langsamer wurde :D.
-
Mit Alt-VB6 habe ich 15.000 Datensätze (mit Unterabfragen) innerhalb von 5 Sek. ausgelesen (mehrere JOINS) und in ein MSHFlexGrid gefüllt. Demnach sollten Deine 300 Datensätze bedeutend schneller sein, bzw. so schnell, dass Du nicht von langsam sprichst.
Mein obiges Beispiel mit JOINS, hat das nicht geholfen? Immerhin sieht Deine Art der JOIN-Bildung mit 'sorte'-n sehr rustikal und umständlich aus. Daran kannst Du doch arbeiten, nicht? - Wenn Deine Anweisung bereits bei 300 Datensätzen langsam ist, wie soll es (wenn auch für Dich unwahrscheinlich) bei (nur) 3000 aussehen?
Für gewöhnlich gehören solche Anweisungen wie 'AND gsorte1.sorte = 0 AND gsorte1.art = 5' nicht in JOIN-'Verknüpfungen'. Ein oder zwei JOIN und dazu ein umfassendes WHERE ist bedeutend schneller. Daher frage ich nach meinem obigen Beispiel. Schon probiert.
Vielleicht solltest Du mal die Tabellen exportieren (in Form von SQL-Anweisungen) und ich könnte es mir zu Hause anschauen.
-
Da binich grad bei das zu probieren ansonsten poste ich gleich mal dl link zur db struktur
-
Also irgendwie raff ich das nicht ^^
Wenn ich das so wie du mache hab ich doch mehrere Datensätze zu einem Vieh, also
allgemeinedatentier1 futterdatentier1sorte1,
allgemeinedatentier1 futterdatentier1sorte2,
allgemeinedatentier1 futterdatentier1sorte3,
allgemeinedatentier1 futterdatentier1sorte4,
allgemeinedatentier2 futterdatentier1sorte1,
allgemeinedatentier2 futterdatentier1sorte2,
allgemeinedatentier2 futterdatentier1sorte3,
allgemeinedatentier2 futterdatentier1sorte4,usw..
Ich muss das leider so haben die 4 Futterdaten nebeneinander in einem zusammengebastelten Datensatz stehen, also
allgemeinedatentier1 futterdatentier1sorte1 futterdatentier1sorte2
allgemeinedatentier2 futterdatentier2sorte1 futterdatentier2sorte2und ich habs ma hochgeladen(bzw grad dabei ):
www.die-gaming.de/dls/sqltest.sqlthx schonma
dreaddy
-
(Werde es mir heute Abend anschauen. Im Moment arbeite ich selber an einer Datenbanklösung und diese ist sehr dringend.)
-
Hm.. habs gefunden, tier.gruppe = gkuh.gruppennummer war quatsch in den unteren Zeilen und deshalb ist der irgendwie durcheinander gekommen.
Jetzt habich zwar 31 joins überschritten und ich bekomme die Fehlermeldung "mysql kann nicht mehr als 31 joins verarbeiten" aber das ist ne andre Geschichte