2012-02-06 17 views
49

Lo que necesito es establecer los valores de todos los campos de un registro con una clave particular (la clave es realmente compuesta), insertando el registro si todavía no hay ningún registro con esa clave.¿Cuáles son las diferencias prácticas entre 'REEMPLAZAR' e 'INSERTAR ... EN ACTUALIZACIÓN DE LLAVE DUPLICADA' en MySQL?

REPLACE parece estar destinado a hacer el trabajo, pero al mismo tiempo su página de manual sugiere INSERT ... ON DUPLICATE KEY UPDATE.

¿Cuál de ellos debería elegir y por qué?

El único "efecto secundario" de REPLACE que se me viene a la mente es que incrementaría los valores de autoincremento (afortunadamente no uso ninguno) mientras que INSERT ... ON DUPLICATE KEY UPDATE probablemente no lo haría. ¿Cuáles son las otras diferencias prácticas a tener en cuenta? ¿En qué casos particulares se puede preferir REPLACE sobre INSERT ... ON DUPLICATE KEY UPDATE y viceversa?

+0

INSERT ... ON DUPLICATE KEY UPDATE de hecho también incrementar el contador de incremento automático. No para que se actualice el registro, sino para el siguiente registro insertado. Entonces, si la ID más alta es 10 y usted hace una inserción duplicada, y luego inserta un nuevo valor único, la ID de esa fila se convertirá en 12. – marlar

Respuesta

83

REPLACE realiza internamente una eliminación y luego un inserto. Esto puede causar problemas si tiene una restricción de clave externa que apunta a esa fila. En esta situación, el REPLACE podría fallar o empeorar: si su clave externa está configurada para eliminar en cascada, el REPLACE hará que se eliminen las filas de otras tablas. Esto puede suceder aunque la restricción se cumplió antes y después de la operación REPLACE.

El uso de INSERT ... ON DUPLICATE KEY UPDATE evita este problema y, por lo tanto, es preferible.

+4

+1 ¡Esto es esclarecedor! Fui mordido por esto y nunca lo descubrí. –

+1

Buena respuesta, pero en el caso real de este problema no se va a cumplir. La posibilidad de colisión puede considerarse 50/50. ¿Qué debería elegir entonces? Y como 'INSERTAR ... EN ACTUALIZACIÓN DUPLICADA DE LLAVE' se ve considerablemente "mejor", ¿en qué casos particulares puede "REEMPLAZAR" ser una mejor opción? – Ivan

+1

Investigué un poco y, por lo que puedo ver, no hay una razón común para usar REEMPLAZAR en lugar de INSERTAR ... EN ACTUALIZACIÓN DE LLAVE DUPLICADA. Es esencialmente una característica heredada. A menos que exista alguna razón particular por la cual su código se basa en filas que se eliminan y se vuelven a agregar, con los efectos asociados en índices y valores de incremento automático, no parece haber ningún motivo para usarlo. –

1

Reemplazar parece que realiza dos operaciones en el caso de que la clave ya exista. Tal vez eso implica que hay una diferencia de velocidad entre los dos?

(INSERT) uno contra uno actualización borrar + una pieza de inserción (sustituir)

EDIT: Mi implicación de que reemplace podría ser más lento en realidad es totalmente erróneo. Pues bien, de acuerdo con esta entrada de blog de todos modos ... http://www.tokutek.com/2010/07/why-insert-on-duplicate-key-update-may-be-slow-by-incurring-disk-seeks/

5

Cuando se utiliza en lugar de REPLACEINSERT ... ON DUPLICATE KEY UPDATE, a veces observo problemas clave de bloqueo o punto muerto cuando varias consultas llegan rápidamente para una clave dada. La atomicidad de este último (además de no causar eliminaciones en cascada) es una razón más para usarlo.

2

En lo particular, los casos pueden reemplazar preferible a INSERT ... EN DUPLICATE KEY UPDATE y viceversa?

Me acabo de encontrar la manera más difícil que en el caso de las tablas con un motor de almacenamiento FEDERATED se aceptan INSERT...ON DUPLICATE KEY UPDATE declaraciones, pero fallan (con un error 1022: No se puede escribir; clave en la tabla duplicada .. .) si ocurre una violación de clave duplicada - vea el punto correspondiente en this page del Manual de referencia de MySQL.

Afortunadamente, pude utilizar REPLACE en lugar de INSERT...ON DUPLICATE KEY UPDATE dentro de mi desencadenante de inserción posterior para lograr el resultado deseado de replicar cambios en una tabla FEDERATED.

1

Si no enumera todas las columnas, creo que REPLACE restablecerá las columnas no mencionadas con sus valores predeterminados en las filas reemplazadas. ON DUPLICATE KEY UPDATE no cambiará las columnas no mencionadas.

24

Para responder a la pregunta en términos de rendimiento, hice una prueba utilizando tanto los métodos

Reemplazar En implica:
1.Try inserción en la tabla 2. Si
1 falla, elimine la fila e insertar la nueva fila

insertar en Duplicar actualización de la clave consiste en:
1.Try insertar en la tabla 2. Si
1 falla, actualización de fila

Si todos los pasos involucrados son insertos, no debe haber diferencia en el rendimiento. La velocidad debe depender del número de actualizaciones involucradas. El peor caso es cuando todas las declaraciones son actualizaciones

He intentado ambas declaraciones en mi tabla InnoDB con 62.510 entradas (solo actualizaciones). En velocidades camparing:
Reemplazar En: 77.411 segundos
Insertar en clave duplicada Actualización: 2.446 segundos

Insert on Duplicate Key update is almost 32 times faster. 

Tamaño de la tabla: 1,249,250 filas con 12 columnas en una m3.medium Amazon

+0

Estadísticas interesantes, ¿has intentado' Insertar en clave duplicada reemplazar'? ¿Fue más lento? – radtek

Cuestiones relacionadas