Lo que necesito es establecer los valores de todos los campos de un registro con una clave en particular (la clave es compuesta en realidad), insertando el registro si todavía no hay ningún registro con dicha clave.
REPLACE
parece destinado a hacer el trabajo, pero al mismo tiempo sugiere su página de manual
INSERT ... ON DUPLICATE KEY UPDATE
.
¿Cuáles de ellos debería elegir mejor y por qué?
El único "efecto secundario" de REPLACE
eso que 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 REPLACE
puede preferir INSERT ... ON DUPLICATE KEY UPDATE
y viceversa?
Respuestas:
REPLACE
internamente realiza una eliminación y luego una inserción. Esto puede causar problemas si tiene una restricción de clave externa que apunta a esa fila. En esta situación,REPLACE
podría fallar o peor: si su clave externa está configurada para eliminar en cascada,REPLACE
hará que las filas de otras tablas se eliminen. Esto puede suceder incluso si la restricción se cumplió tanto antes como después de laREPLACE
operación.El uso
INSERT ... ON DUPLICATE KEY UPDATE
evita este problema y, por lo tanto, es preferible.fuente
INSERT ... ON DUPLICATE KEY UPDATE
parece considerablemente "mejor", ¿en qué casos particulares puede "REEMPLAZAR" ser una mejor opción?REPLACE
actualizará su valor de incremento automático de PK si hace unDELETE
yINSERT
. Que es exactamente lo que quiero. No quiero que el consumidor encuentre el registro bajo el mismo PK, por lo que no obtiene filas. Cuando quiero que lo encuentren (actualización real), usoUPDATE
REPLACE
másINSERT ... ON DUPLICATE KEY UPDATE
? ¿Por qué se preferiría unINSERT
+DELETE
sobre unUPDATE
?Para responder a la pregunta en términos de rendimiento, hice una prueba usando ambos métodos
Reemplazar en implica:
1. Intente insertar en la tabla
2. Si 1 falla, elimine la fila e inserte una nueva fila
Insertar en clave duplicada La actualización implica:
1.Intentar insertar en la tabla
2.Si 1 falla, actualizar fila
Si todos los pasos involucrados son insertos, no debería haber diferencia en el rendimiento. La velocidad tiene que depender del número de actualizaciones involucradas. El peor de los casos es cuando todas las declaraciones son actualizaciones.
Probé ambas declaraciones en mi tabla InnoDB que involucran 62,510 entradas (solo actualizaciones). En velocidades de campaña:
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 un Amazon m3.
fuente
Insert on Duplicate Key Replace
? ¿Fue más lento?ON DUPLICATE KEY UPDATE
, no puedes escribirON DUPLICATE KEY REPLACE
. Si desea actualizar todos los valores de la fila existente al duplicar la clave, debe escribirON DUPLICATE KEY UPDATE col1=VALUES(col1), col2=VALUES(col2), ...
: debe enumerar todas las columnas manualmente.Cuando utilizo en
REPLACE
lugar deINSERT ... ON DUPLICATE KEY UPDATE
, a veces observo problemas de bloqueo o interbloqueo de teclas cuando llegan varias consultas rápidamente para una clave determinada. La atomicidad de este último (además de no causar eliminaciones en cascada) es una razón de más para usarlo.fuente
Si no enumera todas las columnas, creo
REPLACE
que restablecerá las columnas no mencionadas con sus valores predeterminados en las filas reemplazadas.ON DUPLICATE KEY UPDATE
dejará las columnas no mencionadas sin cambios.fuente
Acabo de descubrir por las malas que, en el caso de tablas con un motor de almacenamiento FEDERADO, las
INSERT...ON DUPLICATE KEY UPDATE
declaraciones se aceptan, pero fallan (con un Error 1022: No se puede escribir; clave duplicada en la tabla ...) si hay una clave duplicada se produce una infracción: consulte el punto correspondiente en esta página del Manual de referencia de MySQL.Afortunadamente, pude usar en
REPLACE
lugar deINSERT...ON DUPLICATE KEY UPDATE
dentro de mi activador de inserción posterior para lograr el resultado deseado de replicar los cambios en una tabla FEDERADA.fuente
Reemplazar parece que hace dos operaciones en el caso de que la clave ya exista. ¿Quizás eso implica que hay una diferencia de velocidad entre los dos?
(INSERTAR) una actualización frente a una eliminación + una inserción (REEMPLAZAR)
EDITAR: Mi implicación de que el reemplazo podría ser más lento es en realidad completamente incorrecta. Bueno, de acuerdo con esta publicación de blog de todos modos ... http://www.tokutek.com/2010/07/why-insert-on-duplicate-key-update-may-be-slow-by-incurring-disk-seeks /
fuente
"Es posible que en el caso de un error de clave duplicada, un motor de almacenamiento pueda realizar REPLACE como una actualización en lugar de eliminar más insertar, pero la semántica es la misma".
http://dev.mysql.com/doc/refman/5.7/en/replace.html
fuente
REPLACE parece ser necesario a veces porque INSERT IGNORE no parece funcionar con transformaciones de datos.
Si hago esto, solo configuro largerCityPop a sí mismo:
Si hago esto, estoy usando la función GRUPO incorrectamente:
Y si hago esto, MySQL no reconocerá el nombre de la columna:
Esto funciona, pero parece simplemente feo:
fuente
INSERT IGNORE
consulta finalizará correctamente (y emitirá una advertencia) si falla una restricción externa . Si desea detectar un error como este, mejor useON DUPLICATE KEY UPDATE
sinIGNORE
.