Atualize uma tabela MySQL com valores de outra

93

Estou tentando atualizar uma tabela do MySQL com base nas informações de outra.

Minha originalmesa se parece com:

id | value
------------
1  | hello
2  | fortune
3  | my
4  | old
5  | friend

E a tobeupdatedmesa se parece com:

uniqueid | id | value
---------------------
1        |    | something
2        |    | anything
3        |    | old
4        |    | friend
5        |    | fortune

Quero atualizar idem tobeupdatedcom o idde originalbase em value(cordas armazenados em VARCHAR(32)campo).

A tabela atualizada terá a seguinte aparência:

uniqueid | id | value
---------------------
1        |    | something
2        |    | anything
3        | 4  | old
4        | 5  | friend
5        | 2  | fortune

Tenho uma consulta que funciona, mas é muito lenta:

UPDATE tobeupdated, original
SET tobeupdated.id = original.id
WHERE tobeupdated.value = original.value

Isso maximiza minha CPU e, eventualmente, leva a um tempo limite com apenas uma fração das atualizações realizadas (há vários milhares de valores para corresponder). Sei que a correspondência valueserá lenta, mas esses são os únicos dados que tenho para combiná-los.

Existe uma maneira melhor de atualizar valores como este? Eu poderia criar uma terceira tabela para os resultados mesclados, se isso fosse mais rápido?

Tentei o MySQL - como posso atualizar uma tabela com valores de outra tabela? , mas não ajudou muito. Alguma ideia?

Agradecemos antecipadamente por ajudar um novato em MySQL!

Superangel
fonte
2
A sua coluna 'valor' tem um índice?
noodl de
Oi noodl; não, valuenão tem índice no momento.
Superangel de

Respostas:

210
UPDATE tobeupdated
INNER JOIN original ON (tobeupdated.value = original.value)
SET tobeupdated.id = original.id

Isso deve bastar, e realmente está fazendo exatamente o que o seu é. No entanto, eu prefiro a sintaxe 'JOIN' para junções em vez de várias condições 'WHERE', acho que é mais fácil de ler

Quanto à lentidão, qual o tamanho das tabelas? Você deve ter índices em tobeupdated.valueeoriginal.value

EDIT: também podemos simplificar a consulta

UPDATE tobeupdated
INNER JOIN original USING (value)
SET tobeupdated.id = original.id

USINGé uma abreviação quando ambas as tabelas de uma junção têm um nome idêntico key, como id. ou seja, um equi-join - http://en.wikipedia.org/wiki/Join_(SQL)#Equi-join

wired00
fonte
3
Obrigado, wired00! Isso funciona perfeitamente. As tabelas são bastante grandes ( originaltem mais de 100.000 entradas e tobeupdatedmais de 10.000), então segui o conselho seu e de noodl sobre os índices e a consulta inteira agora termina em menos de um segundo. Não acredito na diferença !? Muito obrigado pela sua ajuda; Aprendi muito!
Superangel de
5
É ótimo ouvir isso :) Eu também aprendo muito aqui. Eu realmente gosto deste site, pois você pode ser exposto a muitos problemas e ideias diferentes
wired00
obrigado .. Eu tentei tantas coisas do stackoverflow .. este finalmente funcionou
Jaxx0rr
Só queria mencionar que um simples UPDATE com WHERE é muito mais rápido do que a sintaxe JOIN. Cerca de 10.000 linhas.
Alex2php de
1
O ingrediente principal é, obviamente, atribuir como índice. levou-me a atualizar os registros de 300 mil em 4 segundos, em oposição aos tempos limite sem eles.
Amjo
0

Depende de qual é o uso dessas tabelas, mas você pode considerar colocar o gatilho na tabela original ao inserir e atualizar. Quando a inserção ou atualização for concluída, atualize a segunda tabela com base em apenas um item da tabela original. Vai ser mais rápido.

firegnom
fonte
Obrigado firegnom; Nunca usei gatilhos antes, mas com certeza lerei sobre eles.
Superangel de