Mysql
 sql >> Datenbank >  >> RDS >> Mysql

MySQL-Hash-Indizes zur Optimierung

Zunächst zu den spezifischen Fragen, die Sie aufwerfen:

  1. 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 im MEMORY verfügbar und NDB Speicher-Engines:daher möglicherweise nicht einmal eine Option für Sie.

    Beachten Sie außerdem, dass Indizes auf Kombinationen von ID und Lookup allein ist möglicherweise nicht optimal, da Ihr WHERE Prädikat filtert auch nach tablea.Elg_IDpart1 und tableb.IDpart1 – Sie können auch von der Indizierung dieser Spalten profitieren.

  2. Vorausgesetzt, dass die gewünschten Indextypen von der Speicher-Engine unterstützt werden, können Sie sie nach Belieben mischen.

  3. Sie könnten einen Indexhinweis verwenden um MySQL zu zwingen, andere Indizes zu verwenden als die, die der Optimierer sonst ausgewählt hätte.

  4. 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.