Thomas: MySQL Abfrage

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

  1. 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!

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

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

        --
        sh:( fo:| ch:? rl:( br:> n4:~ ie:% mo:} va:) de:] zu:) fl:{ ss:) ls:& js:|
      2. 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