Mysql
 sql >> Base de données >  >> RDS >> Mysql

Index de hachage MySQL pour l'optimisation

Tout d'abord, pour répondre aux questions spécifiques que vous soulevez :

  1. 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 la MEMORY et NDB 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 et Lookup seul peut ne pas être optimal, car votre WHERE le prédicat filtre également sur tablea.Elg_IDpart1 et tableb.IDpart1 - vous pouvez également bénéficier de l'indexation sur ces colonnes.

  2. À 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.

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

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