Jörg: Flaschenhals bei Query finden (mysql(i))

Beitrag lesen

Hallo Rolf,

vorab vielen Dank für Deine Hilfe. Vielen Dank auch für Deine späte Nachricht gestern abend noch. Ich habe die noch spät in der Nacht gelesen und konnte schon gedanklich "damit arbeiten", auch wenn ich erst heute morgen antworte.

Jetzt muss ich nur versuchen, Dir auf Deine Fragen zu antworten, von denen mir noch nicht alle ganz klar sind. Aber der Reihe nach...

Zuerstmal meine "..." in der Query, da habe ich nur zusätzliche Spalten mit dem Alias "r" herausgenommen, also fehlt da inhaltlich nichts zur Query. Dann habe ich zusätzlich noch meine LIMIT-Angaben herausgenommen. Das erklärt dann auch mein SQL_CALC_FOUND_ROWS.

(1) Du verwendest einen GROUP BY RechnungsNummer. Der sorgt dafür, dass dein Output zu jeder Rechnungsnummer genau eine Row enthält. Zusätzlich hast Du einen DISTINCT drin. Der sorgt dafür, dass dein Ergebnis keine Duplikate enthält. Es ist nun relativ egal, ob der DISTINCT vor oder nach der Gruppierung ausgeführt wird, aber solange Du zum GROUP BY keine Aggregierungsfunktionen verwendest, ist das Ergebnis mit und ohne DISTINCT das Gleiche. Er kostet aber einen Durchlauf durch die Daten, um Duplikate zu ermitteln.

Ok. Das Weglassen des "DISTINCTS" habe ich mal ausprobiert, das hat aber keinen merklichen zeitlichen Vorteil gebracht.

(2) Ich hab Dir das sicherlich schon mehrfach erklärt. GROUP BY verlangt, dass jede Spalte, die nicht zum Gruppieren genutzt wird, aggregiert werden muss.

Möglicherweise hast Du das. Vielleicht hab ichs einfach nochn nicht kapiert, was das genau heißt. Kannst Du mir das nochmal an einem Beispiel klar machen?

Brauchst Du den GROUP BY? Hat deine Rechnungen-Tabelle zu einer Rechnungsnummer mehrere Rows?

Hmm. Die Rechnungstabelle selber hat zu jeder Rechnungsnummer genau eine einzige Zeile.
Es kann zu jeder Rechnungsnummer natürlich aus anderen Tabellen mehrere Einträge geben, so können natürlich mehrere Zahlungseingänge o.ä. zu einer Rechnungsnummer vorhanden sein, aber die Rechnungentabelle hat nur 1 Zeile je Rechnungsnummer.

Das ist kein Kritteln neben dem Thema. Ein GROUP BY kann Aufwand kosten, der ggf. nicht nötig ist.

Ja ok, so verstehe ich das auch.👍

(3) Ich würde auch gerne wissen, was aus dem Rows=2 bei den Datevbelegen zu deuten ist. Gibt es zu einer RechnungenID unterschiedliche ListenIDs in der Datevbelete-Tabelle?

Es gibt zu jeder RechnungenID mindestens einen, meist aber 2 Datevbelege, nämlich einmal den RG-Betrag und einmal die UsT (falls angefallen). Unterschiedliche ListenIDs zu einer RG sollte es nicht geben. Die ListenID steht für die Liste, die der User (meist monatlich) für den Datevexport generiert.

(4) Du verwendest SQL_CALC_FOUND_ROWS. Warum? Du hast keine LIMIT Klausel drin. SQL_CALC_FOUND_ROWS ist interessant für eine paginierte Ansicht, bei der man die Gesamtzahl der Zeilen wissen möchte, um sowas wie "Seite drölf von umpfzig" ausgeben zu können.

Sorry, ich hatte das LIMIT herausgenommen, genau dafür verwende ich SQL_CALC_FOUND_ROWS.

(5) Als nächstes sehe ich da den Datev-Join. Wie ist dein Mengengerüst? Kann es für eine RechnungenID tatsächlich mehrere unterschiedliche ListenIDs geben? Ist das fachlich so? Dem Explain sehe ich das nicht an und deine Daten kenne ich nicht.

Beantwortet meine Antwort zu Punkt 3 diese Frage oder soll ich nochmal etwas genauer erklären? Rein von der Logik her würde ich behaupten, dass für eine RechnungenID überhaupt keine unterschiedlichen ListenbIDs existieren dürfen. Selbst wenn ich eine RG schreibe, sie im nächsten monat gutschreibe und wieder inen Monat später neu berechne, ist das nicht so. Denn dann erhält sowohl die Gutschrift als auch die neue RG jeweils eine neue RechnungenID (GU und RG sind bei mir beides "Rechnungen", daher erhält auch die GU eine RechnungenID.

(6) Wozu joinst Du die Berechnungen? Du machst dem Anschein nichts damit. Vermutlich steckt das im "..." Bereich. Im Explain steht 1524 Rows. Wieviele Rows hat die Berechnungen-Tabelle, wieviele Rows pro RechnungenID? Kann diese 1524 deine Datenmenge interimsmäßig explodieren lassen? Der GROUP BY würde sie wieder eindampfen, auf eine Row für eine Rechnungsnummer, aber was ist dann der Zweck des Ganzen?

Oh. Womöglich habe ich in der Vergangenheit mal was damit gemacht, was dann später wieder entfiel? Keine Ahnung. Aber ein Wegnehmen dieses JOINS bringt tatsächlich schonmal Einiges. Im Test (ok, solche Tests sind nicht ganz zuverlässig, ich weiß...) konnte ich die Durchlaufzeit der Query jedenfalls durch Weglassen dieses JOINS schonmal erheblich (auch 40%) reduzieren.

Ob sich noch mehr tun lässt, hängst jetzt auch von deinen Antworten ab…

Hoffe, da ist noch etwas Brauchbares dabei. Ansonsten bitte nochmal nachfragen, jedenfalls vielen lieben Dank für die Hilfe!! 👍

Jörg