MySQL Abfrage
Thomas
- datenbank
Guten Morgen,
gleich vorweg: ich habe hier eine Datenbank, die ich nicht verändern kann.
Ich kann also keinen Index vergeben oder dergleichen. (Index sollte aber vergeben sein)
Kann man folgende Abfrage irgendwie schneller machen?
Das ist Wahnsinn wie lange die teilweise braucht, selbst wenn ich nur 1 Tag von einem Vertreter abfragen lassen will.
:vertreter, :vondate, :bisdate werden von mir eingesetzt.
----------------------------------------------------
select
produktgruppe.p_name,
SUM (rechnungpos.r_gesamtwert) AS summe
from
rechnung,kunde,vertreter,vertreter_kunde,
rechnungpos,auftragpos,produkt,produktgruppe,produkt_produktgrp
where
rechnung.r_kunde_id = kunde.k_id
and vertreter_kunde.v_kunde_id = kunde.k_id
and vertreter_kunde.v_vertreter_id = vertreter.v_id
and vertreter.v_id=:vertreter
and rechnungpos.r_rechnung_id = rechnung.r_id
and rechnungpos.r_auftragpos_id = auftragpos.a_id
and auftragpos.a_produkt_id = produkt.p_id
and produkt.p_id = produkt_produktgrp.p_produkt_id
and produkt_produktgrp.p_produktgrp_id = produktgruppe.p_id
and produktgruppe.p_nr != '1'
and produktgruppe.p_nr != '2'
and produktgruppe.p_nr != '3'
and produktgruppe.p_nr != '4'
and produktgruppe.p_nr != '5'
and (rechnung.r_datum_faellig >= :vondate and rechnung.r_datum_faellig < :bisdate)
group by produktgruppe.p_name
order by produktgruppe.p_name ASC
----------------------------------------------------
Vielen Dank schon mal.
Grüße
Hi!
ich habe hier eine Datenbank, die ich nicht verändern kann.
Das ist schlecht und wird vermutlich das Haupt-Hindernis sein, eine zufriedenstellende Lösung zu finden.
Ich kann also keinen Index vergeben oder dergleichen. (Index sollte aber vergeben sein)
Wo die Indexe liegen, wäre interessant und vor allem, ob sie überhaupt genutzt werden. Das sagt dir der Ausführungsplan deines DBMS, welchen du mit einem vorangestellten EXPLAIN bekommst.
Kann man folgende Abfrage irgendwie schneller machen?
Interessant wäre auch der Aufbau der Tabellen. So kann man ihn nur anhand der Verknüpfungsbedingungen erraten. Apropos Verknüpfungsbedingungen: Diese lassen sich syntaktisch besser von den Auswahlverknüpfungen unterscheiden, wenn man die explizite JOIN-Syntax verwendet. Die Geschwindigkeit wird das nicht beinflussen, nur die des Lesers.
Das ist Wahnsinn wie lange die teilweise braucht, selbst wenn ich nur 1 Tag von einem Vertreter abfragen lassen will.
Außer einer kleinen Verkürzung durch den Einsatz von IN() fällt mir nichts ein. Ein Index auf rechnung.r_datum_faellig wäre vermutlich hilfreich. Teste deine Versuche stets auch mit EXPLAIN, um zu sehen, wo ein full table scan statt eines Index verwendet wird und dränge bei den Datenbankverantwortlichen auf eine Änderung. Dazu ist es vermutlich hilfreich, wenn du beweisen kannst, dass die Änderung was bringt. Das könntest du an einem zum Test parallel aufgesetzten System probieren und vorführen.
SELECT
produktgruppe.p_name,
SUM (rechnungpos.r_gesamtwert) AS summe
FROM rechnung
JOIN kunde ON rechnung.r_kunde_id = kunde.k_id
JOIN vertreter_kunde ON vertreter_kunde.v_kunde_id = kunde.k_id
JOIN vertreter ON vertreter_kunde.v_vertreter_id = vertreter.v_id
JOIN rechnungpos ON rechnungpos.r_rechnung_id = rechnung.r_id
JOIN auftragpos ON rechnungpos.r_auftragpos_id = auftragpos.a_id
JOIN produkt ON auftragpos.a_produkt_id = produkt.p_id
JOIN produkt_produktgrp ON produkt.p_id = produkt_produktgrp.p_produkt_id
JOIN produktgruppe ON produkt_produktgrp.p_produktgrp_id = produktgruppe.p_id
WHERE
vertreter.v_id = :vertreter AND
produktgruppe.p_nr NOT IN ('1', '2', '3', '4', '5') AND
rechnung.r_datum_faellig >= :vondate AND
rechnung.r_datum_faellig < :bisdate
GROUP BY produktgruppe.p_name
ORDER BY produktgruppe.p_name ASC
ORDER BY kann entfallen, da ein GROUP BY unter MySQL automatisch sortiert (wird aber keinen Geschwindigkeitsvorteil bringen).
Ein
rechnung.r_datum_faellig BETWEEN :vondate AND :bisdate
scheitert vorläufig daran, dass es das bisdate einschließen würde, du es aber ausgeschlossen haben möchtest, was sich aber durch ein Verringern des bisdate um einen Tag ändern ließe. Ob es einen Geschwindigkeitsvorteil bringt? Teste es!
Lo!
Das ist schlecht und wird vermutlich das Haupt-Hindernis sein, eine zufriedenstellende Lösung zu finden.
Das habe ich mir schon gedacht und deshalb auch gleich angemerkt.
Diese lassen sich syntaktisch besser von den Auswahlverknüpfungen unterscheiden, wenn man die explizite JOIN-Syntax verwendet. Die Geschwindigkeit wird das nicht beinflussen, nur die des Lesers.
Ja ich weiß. Irgendwie konnte ich mich mit der JOIN-Syntax noch nie so wirklich anfreunden. Seltsamer weiße finde ich sie sogar unübersichtlicher ;)
ORDER BY kann entfallen, da ein GROUP BY unter MySQL automatisch sortiert (wird aber keinen Geschwindigkeitsvorteil bringen).
Ah, das wusste ich gar nicht. Man lernt nie aus.
Ob es einen Geschwindigkeitsvorteil bringt? Teste es!
Ich konnte keinen wirklichen Vorteil feststellen, leider.
Ich werde mich da jetzt noch ein wenig dran machen und schauen ob ich eventuell doch was an der Datenbank ändern kann.
Auf jeden Fall mal Danke für deine kompetente Antwort.
Grüße
Mahlzeit Thomas,
Ja ich weiß. Irgendwie konnte ich mich mit der JOIN-Syntax noch nie so wirklich anfreunden.
Das lässt sich doch ändern ... :-)
Seltsamer weiße finde ich sie sogar unübersichtlicher ;)
Echt? Ich finde es eher übersichtlicher, wenn ich sofort sehe, über welche Felder Tabellen miteinander "verknüpft" sind. Bei der impliziten JOIN-Syntax hast Du erst eine (beliebig sortierte) Liste von Tabellen und danach ein mehr oder weniger komplexes WHERE-Statement, aus dem Du Dir die passenden Teile erst mühselig herausfischen musst ... und das findest Du übersichtlicher? ;-)
MfG,
EKKi
yo,
Ja ich weiß. Irgendwie konnte ich mich mit der JOIN-Syntax noch nie so wirklich anfreunden. Seltsamer weiße finde ich sie sogar unübersichtlicher ;)
ist reine gewohnheit, was der bauer nicht kennt...wenn du dich an diese art der join schreibweise gewöhnt hast, willst du sie nicht mehr misse.
Ich werde mich da jetzt noch ein wenig dran machen und schauen ob ich eventuell doch was an der Datenbank ändern kann.
das wichtigste fehlt noch, dein ausführungsplan. von ganze entscheidener bedeutung wird auch sein, welche die treibende tabellen sind, also wann welcher join ausgeführt wird.
zusätzlich ist es immer besser in der where klausel anzugeben, was rein soll anstelle zu negieren, sprich wenn du bei der produktgruppe.p_nr die bennen kannst, die rein sollen, hast du schon mal einiges gewonnen. geht das nicht würde ich es sogar mit einer unterabfrage machen, die in diesem falle nicht korreliert, also nur einmal ausgeführt wird und dann den IN operator mit der unterabfrage einbinden.
und last but not least, schau mal ob due dir die tabelle vertreter nicht sparen kannst, da du ja sowieso den schlüssel dazu in der hand hälst.
Ilja