Hier ist ein Szenario, das erst kürzlich bei der Arbeit aufgetaucht ist.
Betrachten Sie drei Tabellen, A, B, C.
A hat 3.000 Zeilen; B hat 300.000.000 Zeilen; und C hat 2.000 Zeilen.
Fremdschlüssel sind definiert: B (a_id), B (c_id).
Angenommen, Sie hatten eine Abfrage, die folgendermaßen aussieht:
select a.id, c.id
from a
join b on b.a_id = a.id
join c on c.id = b.c_id
Nach meiner Erfahrung kann MySQL in diesem Fall C -> B -> A wählen. C ist kleiner als A und B ist enorm und sie sind alle gleichwertig.
Das Problem ist, dass MySQL nicht unbedingt die Größe des Schnittpunkts zwischen (C.id und B.c_id) und (A.id und B.a_id) berücksichtigt. Wenn die Verknüpfung zwischen B und C genauso viele Zeilen wie B zurückgibt, ist dies eine sehr schlechte Wahl. Wenn das Beginnen mit A B auf so viele Zeilen wie A heruntergefiltert hätte, wäre es eine viel bessere Wahl gewesen. straight_join
könnte verwendet werden, um diese Reihenfolge wie folgt zu erzwingen:
select a.id, c.id
from a
straight_join b on b.a_id = a.id
join c on c.id = b.c_id
Jetzt a
muss vorher noch mitgemacht werden b
.
Im Allgemeinen möchten Sie Ihre Verknüpfungen in einer Reihenfolge ausführen, in der die Anzahl der Zeilen in der resultierenden Menge minimiert wird. Es ist daher ideal, mit einer kleinen Tabelle zu beginnen und so zu verbinden, dass die resultierende Verknüpfung ebenfalls klein ist. Die Dinge werden birnenförmig, wenn man mit einem kleinen Tisch beginnt und ihn mit einem größeren Tisch verbindet, der genauso groß ist wie der große Tisch.
Es ist jedoch abhängig von den Statistiken. Wenn sich die Datenverteilung ändert, kann sich die Berechnung ändern. Dies hängt auch von den Implementierungsdetails des Join-Mechanismus ab.
Die schlimmsten Fälle, die ich für MySQL gesehen habe, die alles andere als erforderlich sind, straight_join
oder aggressive Indexhinweise, sind Abfragen, die über viele Daten in einer strengen Sortierreihenfolge mit Lichtfilterung paginieren. MySQL bevorzugt nachdrücklich die Verwendung von Indizes für Filter und Verknüpfungen über Sortierungen. Dies ist sinnvoll, da die meisten Benutzer nicht versuchen, die gesamte Datenbank zu sortieren, sondern nur eine begrenzte Teilmenge von Zeilen haben, die auf die Abfrage reagieren. Das Sortieren einer begrenzten Teilmenge ist viel schneller als das Filtern der gesamten Tabelle, unabhängig davon, ob sie sortiert ist oder nicht nicht. In diesem Fall wollte ich die direkte Verknüpfung unmittelbar nach der Tabelle mit der indizierten Spalte setzen, die ich nach festen Dingen sortieren wollte.
straight_join
.