Folgendes Szenario hat sich erst kürzlich bei der Arbeit ergeben.
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 haben eine Abfrage, die wie folgt aussieht:
select a.id, c.id
from a
join b on b.a_id = a.id
join c on c.id = b.c_id
Meiner Erfahrung nach kann MySQL in diesem Fall den Weg C -> B -> A wählen. C ist kleiner als A und B ist riesig, und sie sind alle equijoins.
Das Problem ist, dass MySQL nicht unbedingt die Größe der Schnittmenge zwischen (C.id und B.c_id) und (A.id und B.a_id) berücksichtigt. Wenn die Verknüpfung zwischen B und C genau so viele Zeilen wie B zurückgibt, dann ist es eine sehr schlechte Wahl; wenn das Beginnen mit A B auf so viele Zeilen wie A heruntergefiltert hätte, dann 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 vor dem Einschalten von b
.
Im Allgemeinen möchten Sie Ihre Joins in einer Reihenfolge durchführen, die die Anzahl der Zeilen in der Ergebnismenge minimiert. Es ist also ideal, mit einer kleinen Tabelle zu beginnen und die Verknüpfung so durchzuführen, dass die resultierende Verknüpfung ebenfalls klein ist. Wenn Sie mit einer kleinen Tabelle beginnen und diese mit einer größeren Tabelle verbinden, wird die resultierende Menge genauso groß wie die große Tabelle.
Das ist allerdings statistikabhängig. Wenn sich die Datenverteilung ändert, kann sich auch die Berechnung ändern. Sie hängt auch von den Implementierungsdetails des Verknüpfungsmechanismus ab.
Die schlimmsten Fälle, die ich für MySQL gesehen habe, die alles andere als erforderlich waren straight_join
oder aggressives Index Hinting sind Abfragen, die über eine Menge von Daten in einer strengen Sortierreihenfolge mit leichter Filterung paginieren. Das macht Sinn, weil die meisten Leute nicht versuchen, die gesamte Datenbank zu sortieren, sondern eher eine begrenzte Teilmenge von Zeilen haben, die auf die Anfrage reagieren, und das Sortieren einer begrenzten Teilmenge viel schneller ist als das Filtern der gesamten Tabelle, egal ob sie sortiert ist oder nicht. In diesem Fall hat die direkte Verknüpfung unmittelbar nach der Tabelle mit der indizierten Spalte, nach der ich sortieren wollte, Abhilfe geschaffen.