Tout d'abord, pour répondre aux questions spécifiques que vous soulevez :
-
Comme documenté sous
CREATE INDEX
Syntaxe :Par conséquent, avant même de considérer
HASH
l'indexation, il faut savoir que c'est seulement disponible dans laMEMORY
etNDB
moteurs de stockage :ce n'est peut-être même pas une option pour vous.De plus, sachez que les index sur les combinaisons de
ID
etLookup
seul peut ne pas être optimal, car votreWHERE
le prédicat filtre également surtablea.Elg_IDpart1
ettableb.IDpart1
- vous pouvez également bénéficier de l'indexation sur ces colonnes. -
À condition que les types d'index souhaités soient pris en charge par le moteur de stockage, vous pouvez les mélanger comme bon vous semble.
-
Vous pouvez utiliser un indice d'index pour forcer MySQL à utiliser des index différents de ceux que l'optimiseur aurait autrement sélectionnés.
-
C'est habituellement assez intelligent, mais pas toujours. Dans ce cas, cependant, il a probablement déterminé que la cardinalité des index est telle qu'il vaut mieux utiliser ceux qu'il a choisis.
Désormais, selon la version de MySQL que vous utilisez, les tables dérivées de sous-requêtes peuvent ne pas avoir d'index pouvant être utilisés pour un traitement ultérieur :par conséquent, la jointure avec b
peut nécessiter une analyse complète de cette table dérivée (il n'y a pas suffisamment d'informations dans votre question pour déterminer exactement à quel point cela pourrait être un problème, mais schema1.tableb
avoir 1,5 million d'enregistrements suggère que cela pourrait être un facteur important).
Voir Optimisation des sous-requêtes pour plus d'informations.
Il faut donc essayer d'éviter autant que possible d'utiliser des tables dérivées. Dans ce cas, il ne semble pas y avoir de but à votre table dérivée car on pourrait simplement joindre schema1.tablea
et schema1.tableb
directement :
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
La seule chose qui a été perdue est le filtre pour DISTINCT
enregistrements, mais les enregistrements en double vont simplement (tenter de) remplacer les valeurs mises à jour par ces mêmes valeurs à nouveau, ce qui n'aura aucun effet, mais peut s'avérer très coûteux (surtout avec autant d'enregistrements dans cette table).
L'utilisation de ORDER BY
dans la table dérivée était inutile car on ne pouvait pas s'y fier pour obtenir un ordre particulier vers le UPDATE
, alors que dans cette version révisée, il veillera à ce que toutes les mises à jour qui écrasent les précédentes aient lieu dans l'ordre spécifié :mais est-ce nécessaire ? Peut-être peut-il être supprimé et économiser sur toute opération de tri.
Il faut vérifier les prédicats dans le WHERE
clause :sont-elles toutes nécessaires (la clause NOT NULL
vérifie a.ID
et b.Lookup
, par exemple, sont superflus étant donné qu'un tel NULL
les enregistrements seront éliminés par le JOIN
prédicat) ?
Au total, cela nous laisse avec :
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
Ce n'est que si les performances ne sont toujours pas satisfaisantes qu'il faut approfondir l'indexation. Sont des colonnes pertinentes (c'est-à-dire celles utilisées dans le JOIN
et WHERE
prédicats) indexés ? Les index sont-ils sélectionnés pour être utilisés par MySQL (gardez à l'esprit qu'il ne peut en utiliser qu'un index par table pour les recherches :pour tester à la fois le JOIN
prédicat et les prédicats de filtre :peut-être avez-vous besoin d'un index composite approprié) ? Vérifiez le plan d'exécution de la requête en utilisant EXPLAIN
pour enquêter davantage sur ces problèmes.