Rolf B: Flaschenhals bei Query finden (mysql(i))

Beitrag lesen

Hallo Jörg,

mir ist schlecht. Was für eine Höllenquery. Aus vielen Gründen...

(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.

(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. Die große Macke von MYSQL ist, dass es das nicht erzwingt. Statt dessen benutzt es einfach irgendeinen Satz aus der Gruppe. Soweit ich weiß ist das der, den es beim Gruppieren zuerst antrifft. Ob das der richtige ist, hängt von der Anordnung der Daten in den Tabellen ab (d.h. unter anderem vom clustering index).

Brauchst Du den GROUP BY? Hat deine Rechnungen-Tabelle zu einer Rechnungsnummer mehrere Rows? Wenn ja: Was ist dann mit den anderen r-Spalten, die Du nutzt? Haben die für eine Rechnungsnummer alle den gleichen Wert? Hier ist entweder eine Quelle für falsche Datenauswahl, oder ein Indiz für einen groben Normalisierungsfehler.

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

(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?

(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. Hier steht eine Info der MYSQL Entwickler zu dieser Option, sie soll abgeschafft werden. Unter anderem, weil sie langsam ist. Brauchst Du SQL_CALC_FOUND_ROWS für eine nachfolgenden SELECT FOUND_ROWS()? Wenn nicht, weg damit, diese Klausel hat keine andere Existenzberechtigung. Und wenn Du diesen SELECT machst - warum? Ohne LIMIT ist er sinnlos, du liest die Rows alle nach PHP und kannst sie dabei zählen.

(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.

(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?

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

Rolf

--
sumpsi - posui - obstruxi