Thema: Delphi [SQL] Abfrage tunen

Einzelnen Beitrag anzeigen

omata

Registriert seit: 26. Aug 2004
Ort: Nebel auf Amrum
3.154 Beiträge
 
Delphi 7 Enterprise
 
#15

Re: [SQL] Abfrage tunen

  Alt 31. Mär 2006, 19:27
@Igotcha:
Schön das es dir geholfen hat.
Ich bin erstaunt, dass MySQL endlich Views kann - super!
Das eine etwas komplexere Abfrage nicht als View erstellt werden kann zeigt scheinbar die Wirklichkeit von MySQL-Views, schade. Alternative ist vielleicht eine Stored Procedure?
In MSSQL gibt es für solche Probleme Benutzerdefinierte Funktionen die kann man dann wie Tabellen/Views in einer Abfrage benutzen (nur mit noch komplizierterem Innenleben).

Ich benutzte als ersten Schritt gern LEFT JOINs zum Optimieren von Abfragen. Wenn das nicht reicht, kommen die von alzaimar angesprochenen temporäreren Tabellen (aber nur wenn es nicht anders geht, ich finde SQL-Abfragen schöner als serverseistige Prozeduren/Funktionen)

Bei MySQL besonders < 4.1 bieten sich LEFT JOINs sehr an, weil es dort keine Unterabfragen gibt. In LEFT JOINs werden die Tabelleninhalte unabhängig voneinander erstellt. Wenn man also mehr als einen LEFT JOIN hat, können diese wirklich parallel ausgeführt werden. Das bringt wirklich sehr schnelle Ergebnisse (wenn das DB-System Parallelarbeit unterstützt).
Viele werden das jetzt bestimmt wieder anders sehen. Diese Rumnörgler kann ich nur bedauern und sage einfach: Ok mach weiter mit deinen langsamen Abfragen oder unübersichtlichen Stored Procedures.

Die CASE-Verteiler sind der eigentliche Trick. Du holst dir die gesamte Tabelle und schaltest die Inhalte der Spalten, die addiert werden sollen nur dann frei, wenn das Ergebnis in die Zählung einfliessen soll. Wenn nicht, wird einfach eine Nul dazuaddiert. Das geht wesentlich schneller und es ist nur ein Abfrage.

Und noch eins: Bei MySQL < 4.1 kann man mit LEFT JOINs sehr schön Unterabfragen simullieren.
Warum < 4.1? naja, wird noch oft benutzt und ist noch super schnell (im Vergleich zu MySQL >= 4.1)

@alzaimar:
Sehe ich genauso, es geht nichts über MSSQL, die Datenbank ist einfach nur genial.
(diese Geschwindigkeit ist einfach ein Traum)

Allerdings muss ich sagen habe ich auch schon den MSSQL-Server an seine Grenzen geführt.
Fehler: Sie haben mehr als 256 Tabellen im Zugriff - Anweisung beendet.
Ups, das war nicht nett. Aber ich habe es trotzdem gelöst


EDIT: @Igotcha

so habe mich nochmal damit beschäftigt und mir MySQL5 installiert.
Die Unterabfragen in den LEFT JOINs mag MySQL nicht in einem View. Lösung: zerlege meine Abfrage und mach aus den Unterabfragen auch Views...

View_Left1
SQL-Code:
CREATE ... VIEW view_left1 AS
SELECT monat, jahr, projektid,
       SUM(plan) AS plank,
       SUM(prognose) AS progk
FROM pim_pb_kue
WHERE ident = 'KOST'
GROUP BY monat, jahr, projektid
View_Left2
SQL-Code:
CREATE ... VIEW view_left2 AS
SELECT jahr, pagid,
       SUM(CASE WHEN zeile IN (61500, 61532, 61536,
                               61547, 61543, 61526,
                               61524, 61512, 61515)
             THEN vorjahr + jan
             ELSE 0
           END) AS umsatz,
       SUM(CASE WHEN zeile IN (23112, 23132, 23135,
                               23162, 23165, 23170,
                               23183, 24753, 34512,
                               34832, 45012, 23182)
             THEN vorjahr + jan
             ELSE 0
           END) AS istk,
       SUM(CASE WHEN zeile = 14000
             THEN vorjahr + jan
             ELSE 0
           END) * 73 AS istkstd
FROM pim_p_ist
GROUP BY jahr, pagid
View_Main
SQL-Code:
CREATE ... VIEW view_main AS
SELECT b.projektid, p.projektname,
       ki.umsatz,
       b.prsituation, b.cbzuag, b.cbengag,
       b.cbrifa, b.cbriman,
       k.plank,
       k.progk,
       ki.istk,
       ki.istkstd,
       p.ende AS planende, b.ende AS progende
FROM pim_pb_berichte b
INNER JOIN pim_p_projekteneu p
  ON b.projektid = p.projektid
LEFT JOIN view_left1 k
  ON b.monat = k.monat
     AND b.jahr = k.jahr
     AND b.projektid = k.projektid
LEFT JOIN view_left2 ki
  ON b.jahr = ki.jahr
     AND b.projektid = ki.pagid
WHERE p.projektstatus = -1
  AND b.jahr = 2006
  AND b.monat = 1
ORDER BY p.projektname ASC
So sollte das gehen.
Jetzt bin ich nur mal auf die Geschwindigkeit gespannt

MfG
Thorsten
  Mit Zitat antworten Zitat