In primo luogo, per affrontare le domande specifiche che sollevi:
-
Come documentato in
CREATE INDEX
Sintassi :Pertanto, prima ancora di considerare
HASH
indicizzazione, si dovrebbe essere consapevoli che è solo disponibile nellaMEMORY
eNDB
motori di archiviazione:quindi potrebbe non essere nemmeno un'opzione per te.Inoltre, tieni presente che gli indici sulle combinazioni di
ID
eLookup
da solo potrebbe non essere ottimale, come il tuoWHERE
il predicato filtra anche sutablea.Elg_IDpart1
etableb.IDpart1
—potresti trarre vantaggio dall'indicizzazione anche su quelle colonne. -
A condizione che i tipi di indice desiderati siano supportati dal motore di archiviazione, puoi combinarli come meglio credi.
-
Potresti usare un suggerimento indice per forzare MySQL a utilizzare indici diversi da quelli che l'ottimizzatore avrebbe altrimenti selezionato.
-
È solitamente abbastanza intelligente, ma non sempre. In questo caso, però, ha probabilmente determinato che la cardinalità degli indici è tale per cui è meglio utilizzare quelli che ha scelto.
Ora, a seconda della versione di MySQL che stai utilizzando, le tabelle derivate dalle sottoquery potrebbero non avere alcun indice che possa essere utilizzato per ulteriori elaborazioni:di conseguenza il join con b
potrebbe richiedere una scansione completa di quella tabella derivata (non ci sono informazioni sufficienti nella tua domanda per determinare esattamente quanto potrebbe essere un problema, ma schema1.tableb
avere 1,5 milioni di record suggerisce che potrebbe essere un fattore significativo).
Vedi Ottimizzazione delle sottoquery per ulteriori informazioni.
Si dovrebbe quindi cercare di evitare di utilizzare tabelle derivate, se possibile. In questo caso, non sembra esserci alcuno scopo per la tua tabella derivata in quanto si potrebbe semplicemente unire schema1.tablea
e schema1.tableb
direttamente:
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
L'unica cosa che è andata persa è il filtro per DISTINCT
record, ma i record duplicati semplicemente (tentano di) sovrascrivere nuovamente i valori aggiornati con quegli stessi valori, il che non avrà alcun effetto, ma potrebbe essersi rivelato molto costoso (specialmente con così tanti record in quella tabella).
L'uso di ORDER BY
nella tabella derivata era inutile in quanto non si poteva fare affidamento per ottenere un ordine particolare per l'UPDATE
, mentre in questa versione rivista assicurerà che tutti gli aggiornamenti che sovrascrivono quelli precedenti avvengano nell'ordine specificato:ma è necessario? Forse può essere rimosso e salvato su qualsiasi operazione di smistamento.
Si dovrebbero controllare i predicati in WHERE
clausola:sono tutti necessari (il NOT NULL
controlla a.ID
e b.Lookup
, ad esempio, sono superflui dato che tali NULL
i record verranno eliminati dal JOIN
predicato)?
Nel complesso, questo ci lascia con:
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
Solo se la performance è ancora insoddisfacente si dovrebbe guardare oltre all'indicizzazione. Sono colonne pertinenti (ovvero quelle utilizzate nel JOIN
e WHERE
predicati) indicizzati? Gli indici sono selezionati per l'uso da parte di MySQL (tieni presente che può usarne solo uno index per table per le ricerche:per testare sia il JOIN
predicato e i predicati del filtro:forse hai bisogno di un indice composito appropriato)? Controlla il piano di esecuzione della query utilizzando EXPLAIN
per indagare ulteriormente su tali problemi.