Ten eerste om de specifieke vragen die u stelt te behandelen:
-
Zoals gedocumenteerd onder
CREATE INDEX
Syntaxis :Daarom, voordat u zelfs maar overweegt
HASH
indexeren, moet men zich ervan bewust zijn dat het alleen beschikbaar in hetMEMORY
enNDB
opslag-engines:dus misschien niet eens een optie voor jou.Houd er bovendien rekening mee dat indexen op combinaties van
ID
enLookup
alleen is misschien niet optimaal, omdat uwWHERE
predikaat filtert ook optablea.Elg_IDpart1
entableb.IDpart1
—u kunt ook profiteren van indexering op die kolommen. -
Op voorwaarde dat de gewenste indextypen worden ondersteund door de opslagengine, kunt u ze naar eigen inzicht mixen.
-
Je zou een indexhint kunnen gebruiken om MySQL te dwingen andere indexen te gebruiken dan die welke de optimizer anders zou hebben geselecteerd.
-
Het is meestal slim genoeg, maar niet altijd. In dit geval heeft het echter waarschijnlijk vastgesteld dat de kardinaliteit van de indexen zodanig is dat het beter is om de indexen te gebruiken die het heeft gekozen.
Afhankelijk van de versie van MySQL die u gebruikt, is het mogelijk dat tabellen die zijn afgeleid van subquery's geen indexen bevatten die voor verdere verwerking kunnen worden gebruikt:bijgevolg wordt de join met b
kan een volledige scan van die afgeleide tabel vereisen (er is onvoldoende informatie in uw vraag om precies te bepalen hoeveel van een probleem dit zou kunnen zijn, maar schema1.tableb
het hebben van 1,5 miljoen records suggereert dat dit een belangrijke factor kan zijn).
Zie Subquery-optimalisatie voor meer informatie.
Men moet daarom proberen om, indien mogelijk, het gebruik van afgeleide tabellen te vermijden. In dit geval lijkt er geen enkel doel te zijn voor uw afgeleide tabel, omdat u zich eenvoudig kunt aansluiten bij schema1.tablea
en schema1.tableb
direct:
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
Het enige dat verloren is gegaan, is het filter voor DISTINCT
records, maar dubbele records zullen eenvoudigweg bijgewerkte waarden (proberen) overschrijven met dezelfde waarden, wat geen effect heeft, maar het kan erg duur zijn gebleken (vooral met zoveel records in die tabel).
Het gebruik van ORDER BY
in de afgeleide tabel was zinloos omdat er niet op kon worden vertrouwd om een bepaalde volgorde van de UPDATE
te bereiken , terwijl het in deze herziene versie ervoor zorgt dat alle updates die eerdere overschrijven plaatsvinden in de opgegeven volgorde:maar is dat nodig? Misschien kan het worden verwijderd en bij elke sorteerbewerking worden opgeslagen.
Men moet de predikaten controleren in de WHERE
clausule:zijn ze allemaal nodig (de NOT NULL
controles op a.ID
en b.Lookup
, zijn bijvoorbeeld overbodig aangezien een dergelijke NULL
records worden verwijderd door de JOIN
predikaat)?
Al met al houden we het volgende over:
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
Pas als de performance nog steeds onvoldoende is, moet men verder kijken naar de indexering. Zijn relevante kolommen (d.w.z. de kolommen die worden gebruikt in de JOIN
en WHERE
predikaten) geïndexeerd? Worden de indexen geselecteerd voor gebruik door MySQL (houd er rekening mee dat er slechts één kan worden gebruikt index per tabel voor lookups:voor het testen van zowel de JOIN
predikaat en de filterpredikaten:misschien hebt u een geschikte samengestelde index nodig)? Controleer het uitvoeringsplan voor de query met behulp van EXPLAIN
om dergelijke problemen verder te onderzoeken.