Michael Schröpl: MySQL: Performaceproblem

Beitrag lesen

Hi Andreas,

Meine Tabelle wird einmal erstellt und dann nur alle halben
Jahre upgedatet (oder geupdatet? Scheiß denglish!)
Das heißt nur SELECT Abfragen ein halbes Jahr?

Vielleicht. Es könnte auch bedeutet, den Index ein halbes Jahr lang
degenerieren zu lassen und ihn anschließen neu aufzubauen.

Die zweimal im Jahr kann ich auch die Inizes neu machen.
Das ist mein Problem - was heißt denn "neu machen"?
Wie mache ich einen Index, der existiert neu?

DROP INDEX und danach wieder CREATE INDEX.

Ich dachte, der würde sich dann bei änderungen selbst aktuali-
sieren, wie ist das jetzt genau?

Das tut er schon ... aber seine Struktur leidet darunter.
Ein Pullover, der an vielen Stellen gestopft ist, wird dadurch
auch nicht besser, auch wenn er immer noch warm hält. ;-)

Und der Unterschied in der Geschwindigkeit wo wirklich so eklatant?

Ja. Du ersetzt einen linearen Aufwand durch einen logarithmischen.

Und nur durch den einen Index?

Streiche "nur". Der Einsatz des Index bedeutet, das gesamte Verfahren
zu ändern. Im Wesentlichen ersetzt Du das Suchen nach einem Datensatz
durch das Nachsehen in einer Sammlung einmalig durchgeführter und
sehr schnell zugänglicher Such-Ergebnisse - Du verlagerst also einen
Teil der Rechenzeit aus dem SELECT in das CREATE INDEX.
(Deshalb dauert das auch so lange!)

War das jetzt weil da so viele gleiche Ergebnisse drin sind?

Ganz im Gegenteil!
Je eindeutiger die Ergebnisse sind, desto besser der Effekt des Index.

Ich habe inzwischen auch eine super Tabelle mit PLZ-Daten und
Bundesländern gefunden, 50.000 DS, das komische, die Tabelle hat
die Spalten ID|Ort|PLZ|Vorwahl|Land|Staat. Ich habe die Tabelle
als DUMP bekommen, udn so waren indices über folgende Spalten
angelegt:
ID: primärschlüssel
Ort: Index
PLZ: Index
Vorwahl: Index
Staat: Index
Zuerst, die Daten selbst machen knapp 1.9 MB Speicherplatz aus, die
Indices 2.5MB! Ist das kein Mißverhältnis?

Nein. Du bezahlst Faktor 2 an Speicherplatz, um Faktor 1000 an Tempo
zu gewinnen!
Der Trade-Off zwischen Speicherplatz und CPU-Zeit ist m. E. der nahe-liegendste Ansatzpunkt für eine Optimierung - der wird Dir noch oft
über den Weg laufen.
Bei einem Cache ist das Verhältnis meistens schlechter.

Warum sollte man einen Index über die PLZ-Spalte erstellen, die
es jede PLZ eh nur einmal gibt? ich dachte das wäre dann
Schwachsinn?!

Genau das Gegenteil ist der Fall.

Dagegen ist kein Index über das Land vorhanden, wovon es ja nur 16
gibt, das wäre doch für einen Index geradezu prädestiniert, oder
habe ich da was grundlegend falsch verstanden?

Ja. ;-)

Ein Zugriff über den Index kostet durchaus auch Rechenzeit - aber
sehr viel weniger, als _sämtliche_ Datensätze zu prüfen.
Wenn Du aber diese Rechenzeit bezahlen mußt, dann willst Du als
Ergebnis möglichst bereits den _exakten_ Treffer haben.
Wenn Dir der Zugriff auf den Indexbaum von 1.5 Millionen Datensätze
noch 100000 Treffer zurück liefert, von denen Du dann über weitere
WHERE-Klauseln fast alle wieder wegwerfen mußt, dann hat der Index
Deine Anforderung nur zum Teil beschleunigt.

Zum Hintergrund, eine normale Abfrage sieht so aus:
SELECT
  objekte.ort
    FROM orte
    LEFT JOIN objekte
       ON orte.plz=objekte.plz
    WHERE orte.Land='$bundesland'
Was würdet Ihr hierfür für Indices empfehlen?

a) Ein Index über das Paar ("plz", "land") in der Tabelle "orte"
b) Ein Index über "plz" in der Tabelle "objekte"

Was die Reihenfolge des Paares angeht, müßte ich wissen, welche der
beiden Spalten eindeutigere Treffer liefert - diese sollte innerhalb
dieses Paares vorne sein.

('Ort' kann ich aus beiden Tabellen nehmen!)

Es mag als Fein-Tuning sinnvoll sein, auch noch "ort" als dritte
Spalte in den Index über "orte" aufzunehmen. Das würde es dem RDBMS
ersparen, überhaupt jemals auf die eigentlichen Tabellenzeilen zuzu-
greifen.

Es reicht allerdings nicht, eine beliebige Abfrage auszuwählen, um
daraus die optimale Struktur der Indexe zu bestimmen - Du mußt viel-
mehr _alle_ möglichen Abfragen kennen und am besten auch noch die
Wahrscheinlichkeit für deren Auftreten.
Wenn Du dann die Kosten für die Ausführung jedes einzelnen Statements
plus deren Wahrscheinlichkeit kennst, kannst Du die Gesamtkosten für
alle Abfragen berechnen. Und _das_ ist die Größe, die Du wahrschein-
lich optimieren willst! Denn von ihr hängt die Last auf Deinem Server
ab. Es kann durchaus sein, daß Du ein einzelnes Statement langsamer
machst, weil ein anderes, wahrscheinlicheres Statement dabei sehr viel
schneller wird.

Es kann aber genauso gut sein, daß Dein Optimierungsziel nicht in
den kleinstmöglichen Gesamtkosten, sondern in der Vermeidung eines
einzelnen Super-GAU liegt.
Nimm Dir mal die Self-Suche als Beispiel: Der Betreiber wird daran
interessiert sein, daß der Mix aus allen Abfragen den Server mög-
lichst wenig belastet - er wird also eine häufige Suche von 0.5 auf
0.2 Sekunden beschleunigen wollen, wenn dafür eine seltene Suche
von 5 auf 20 Sekunden gebremst wird. Für den Besucher, der genau
die 20-Sekunden-Suche braucht, ist das natürlich eine Katastrophe -
deshalb _kann_ das Optimierungsziel durchaus auch beinhalten, daß
keine einzelne Abfrage langsamer als <n> werden darf.

An dieser Stelle gilt noch mehr als für viele andere Forum-Fragen:
Ohne eine _exakte_ Aufgabenstellung bist Du völlig aufgeschmissen.
Es nützt wenig, _irgendwas_ zu optimieren, was später im realen
Einsatz gar nicht entscheidend ist ... das allerdings macht die
Sache so spannend ... ;-)

Viele Grüße
      Michael