Zunächst zu den spezifischen Fragen, die Sie aufwerfen:
-
Wie unter
CREATE INDEX
dokumentiert Syntax :Daher, bevor Sie überhaupt an
HASH
denken indexieren, sollte man sich darüber im Klaren sein, dass es nur ist imMEMORY
verfügbar undNDB
Speicher-Engines:daher möglicherweise nicht einmal eine Option für Sie.Beachten Sie außerdem, dass Indizes auf Kombinationen von
ID
undLookup
allein ist möglicherweise nicht optimal, da IhrWHERE
Prädikat filtert auch nachtablea.Elg_IDpart1
undtableb.IDpart1
– Sie können auch von der Indizierung dieser Spalten profitieren. -
Vorausgesetzt, dass die gewünschten Indextypen von der Speicher-Engine unterstützt werden, können Sie sie nach Belieben mischen.
-
Sie könnten einen Indexhinweis verwenden um MySQL zu zwingen, andere Indizes zu verwenden als die, die der Optimierer sonst ausgewählt hätte.
-
Es ist normalerweise schlau genug, aber nicht immer. In diesem Fall hat es jedoch wahrscheinlich festgestellt, dass die Kardinalität der Indizes so ist, dass es besser ist, die von ihm ausgewählten zu verwenden.
Nun, abhängig von der verwendeten MySQL-Version, können Tabellen, die von Unterabfragen abgeleitet sind, keine Indizes enthalten, die für die weitere Verarbeitung verwendet werden können:folglich der Join mit b
erfordert möglicherweise einen vollständigen Scan dieser abgeleiteten Tabelle (Ihre Frage enthält nicht genügend Informationen, um genau zu bestimmen, wie groß das Problem sein könnte, aber schema1.tableb
1,5 Millionen Datensätze zu haben, deutet darauf hin, dass dies ein bedeutender Faktor sein könnte).
Siehe Unterabfrageoptimierung für weitere Informationen.
Man sollte daher möglichst auf abgeleitete Tabellen verzichten. In diesem Fall scheint Ihre abgeleitete Tabelle keinen Zweck zu haben, da man einfach schema1.tablea
verknüpfen könnte und schema1.tableb
direkt:
UPDATE schema1.tablea a
JOIN schema1.tableb b USING (ID, Lookup)
SET a.Elg_IDpart1 = b.IDpart1,
a.Elg_IDpart2 = b.IDpart2
WHERE a.Elg_IDpart1 IS NULL
AND a.ID IS NOT NULL
AND b.IDpart1 IS NOT NULL
AND b.Lookup IS NOT NULL
ORDER BY ID, Lookup
Das einzige, was verloren gegangen ist, ist der Filter für DISTINCT
Datensätze, aber doppelte Datensätze werden aktualisierte Werte einfach wieder mit denselben Werten (versuchen) zu überschreiben – was keine Wirkung hat, sich aber als sehr kostspielig erwiesen hat (insbesondere bei so vielen Datensätzen in dieser Tabelle).
Die Verwendung von ORDER BY
in der abgeleiteten Tabelle war sinnlos, da man sich nicht darauf verlassen konnte, eine bestimmte Reihenfolge des UPDATE
zu erreichen , während in dieser überarbeiteten Version sichergestellt wird, dass alle Updates, die vorherige überschreiben, in der angegebenen Reihenfolge stattfinden:aber ist das notwendig? Vielleicht kann man es entfernen und sich jede Sortieroperation sparen.
Man sollte die Prädikate im WHERE
überprüfen Klausel:sind sie alle notwendig (die NOT NULL
prüft auf a.ID
und b.Lookup
, sind beispielsweise überflüssig, da solche NULL
Datensätze werden durch JOIN
eliminiert Prädikat)?
Insgesamt bleibt uns damit:
UPDATE schema1.tablea a
JOIN schema1.tableb b USING (ID, Lookup)
SET a.Elg_IDpart1 = b.IDpart1,
a.Elg_IDpart2 = b.IDpart2
WHERE a.Elg_IDpart1 IS NULL
AND b.IDpart1 IS NOT NULL
Nur wenn die Performance immer noch unbefriedigend ist, sollte man sich weiter mit der Indizierung befassen. Sind relevante Spalten (d.h. die im JOIN
und WHERE
Prädikate) indiziert? Werden die Indizes für die Verwendung durch MySQL ausgewählt (beachten Sie, dass es nur einen verwenden kann Index pro Tabelle für Lookups:zum Testen sowohl des JOIN
Prädikat und die Filterprädikate:Vielleicht benötigen Sie einen geeigneten zusammengesetzten Index)? Überprüfen Sie den Abfrageausführungsplan mit EXPLAIN
um solche Probleme weiter zu untersuchen.