Andreas Korthaus: Wie bekomme ich einen JOIN schnell?

Beitrag lesen

Hallo!

weder glaube ich diese Behauptung,

Das ist keine Glaubesnfrage ;-)

noch macht sie überhaupt Sinn: Nicht mySQL erstellt diese Dateien, sondern der jeweilige Tabellentreiber. Und da kann jeder machen, was er will.

ok ;-)

Pro Abfrage auf _eine_ Tabelle, ja. Aber ein JOIN enthält Abfragen auf mehrere Tabellen.

Also im KLartext, wenn ich eine Join über 2 Tabellen mache kann ich maximal 2 Indices verwenden, maximal einen pro Tabelle, richtig?

  1. In beiden Tabellen ist das Berechnen der Werte "schwierig". Dann ist es sinnvoll, beides separat zu berechnen, beide Ergebnismengen zwischenzuspeichern und sie anschließend zu kombinieren. Dies impliziert, beide Mengen nach dem JOIN-Kriterium zu sortieren - und das ist bekanntlich teuer (n * log(n)). Läge bereits ein Index, also ein nach dem Auslese-Kriterium sortierter Baum vor, dann könnte man diesen eventuell nutzen - selbst wenn das JOIN-Kriterium selbst gar nicht Bestandteil der WHERE-Klausel dieses Tabellenzugriffs ist: Es könnte trotzdem die beste verfügbare Methode sein, die Tabelle in dieser Reihenfolge zu traversieren.

Was bedeutet "traversieren"?
Den 1, Satz verstehe ich nicht. Wie will man(mysql) für Werte "berechnen"? Die Tabellen sollen doch verknüptft ewerden, wawum soll man dann in beiden Tabellen alle Werte Sortieren? Ich würde die erste Tabelle durchgehen und gleichzeitig in der 2. Tabelle nach übereinstimmungen Suchen. Aus der Ergebnismenge würde ich dann mit der WHERE-Bedingung filtern. Die erste Tabelle enthält ja erheblich weniger Datensätze, also ist die Schleife in der das geschieht nichtmal so auffwenig.
Weil Du das schreibst, in der Doku steht der Otimizer würde die Verknüpfungsbedingung in die WHERE Bedingung "verschieben", wieso?

  1. Das Finden eines zugehörigen Wertes ist in einer der beiden Tabellen sehr viel einfacher als in der anderen (beispielsweise weil in der einen Tabelle ein UNIQUE INDEX darauf existiert).

Die 2. Tabelle hat einen non_unique Index, aber dafür erheblich weniger Datensätze, die 2. hat einen unique Index, aber nur solange ich die Where-Bedingung außen vorlasse. Dann kann ich über die "join-Spalte" der 2. Tabelle einen Primär-Schlüssel legen. Aber wie gesagt hätte ich dann die Wehre-Bedingung nicht optimiert. Aber da ich ja in der Tabelle nur einne Index verwenden kann, müßte ich auf den unique Primär-Schlüssel verzichten, und einen 3-spaltigen Index über die Spalten b.key(Join-Spalte) b.wert1 und b.wert2 legen(beides WHERE-Bedingung), aber da der Index dann nicht merh Unique ist, wird das Joinen vermutlich langsamer. Außerdem mache ich mir hier ein 2. Problem - wird der Index dann überhaupt verwendet? Ein Index (b.key,b.wert1,b.wert2), in der Doku habe ich dazu nur BEispiele zu WHERE-Bedingungen gelesen, halt das der Index nur verwendet wird, wenn auch in Reihenfolge der Spalten im Index die einzelnen durch AND verknüpften WHERE-Bedingungen stehen. Wie ist das wenn ich 1 Spalte für den JOIN verwende, und 2 für die WHERE-Bedingung?
Nochmal die Abfrage:

SELECT a.key
FROM a
LEFT JOIN b
ON a.key=b.key
WHERE(b.wert1 = $variable1 AND b.wert2 < $variable2)

Beziehung zw. a.key : b.key => n:1

2 Indices:
1.: (a.key) <- non unique
2.: (b.key,b.wert1,b.wert2)

Wäre das so das Optimum?

In diesem Falle weiß der Query Optimizer, daß die Anzahl der Treffer im Wesentlichen durch die Treffer aus der anderen Tabelle bestimmt wird, und er weiß, daß er zu jedem dieser Treffer sehr schnell über den Indexzugriff das passende Gegenstück finden kann. In diesem Fall kann der Query Optimizer sich dafür entscheiden, nicht die beiden Mengen getrennt zu berechnen, sondern nur die zweite und über diese eine Schleife laufen zu lassen, in der jeweils das passende Gegenstück geholt wird. Dies ist insbesondere dann sinnvoll, wenn die Ergebnismenge dann später _nicht_ nach dem JOIN-Kriterium sortiert ausgegeben werden soll - wäre dies der Fall, dann hätten wir nicht viel gewonnen, wenn wir die zunächst nicht notwendige Sortierung später dann doch noch durchführen müßten (mit einer anderen Anzahl von Datensätzen - meistens kleiner, in manchen JOIN-Fällen aber sogar größer).

Sortieren muß ich nicht. Aber das hast Du Dir jetzt überlegt, wie aber ist das in der Praxis? Sind die Indices wie ich oben geschrieben habe das was zu empfehlen ist, oder habe ich noch was falsch verstanden?

Viele Grüße
Andreas

PS: Folgendes Zitat aus der MySQL Doku ist leidr im falschen Posting gelandet ;-)

"In einigen Fällen kann eine Anfrage so optimiert werden, dass Sie Werte abruft, ohne in der Daten-Datei nachzuschlagen. Wenn alle benutzten Spalten einer Tabelle numerisch sind und ein ganz links stehendes Präfix für einen Schlüssel ergeben, können die Werte mit größerer Geschwindigkeit aus dem Index-Baum abgerufen werden:"

das nur mal so zur Diskussion unten ob man besser Strings oder INTEGER einsetzt, wobei das natürlich nur für MySQL so gilt.