2010-10-26 39 views
8

Antes que nada, permítanme decir que estoy usando el marco PHP Yii, por lo que me gustaría permanecer dentro de su conjunto definido de instrucciones SQL si es posible. Sé que probablemente podría crear una gran declaración SQL larga que haría todo, pero prefiero no ir allí.En MySQL, ¿es más rápido eliminar e insertar o es más rápido actualizar las filas existentes?

OK, imagina que tengo una tabla Usuarios y una tabla FavColors. Luego tengo un formulario donde los usuarios pueden seleccionar sus preferencias de color marcando una o más casillas de verificación de una gran lista de colores posibles.

Esos resultados se almacenan como filas múltiples en la tabla FavColors como esta (id, user_id, color_id).

Ahora imagine que el usuario entra y cambia su preferencia de color. En este escenario, ¿cuál sería la forma más eficiente de obtener las nuevas preferencias de color en la base de datos?

Opción 1:

  • Hacer una masa borrar de todas las filas donde user_id coincide
  • luego hacer una inserción masiva de todas las nuevas filas

Opción 2:

  • Pase por cada c urrent row para ver qué ha cambiado y actualizar en consecuencia
  • Si es necesario insertar más filas, hazlo.
  • Si las filas deben borrarse, hágalo.

Me gusta la opción uno porque solo requiere dos afirmaciones, pero algo simplemente se siente mal al eliminar una fila para devolver prácticamente casi los mismos datos. También está la cuestión de hacer que los identificadores aumenten automáticamente a valores más altos más rápidamente, y no sé si eso debería evitarse siempre que sea posible.

La opción 2 requerirá mucho más trabajo de programación, pero evitaría situaciones en las que eliminaría una fila solo para crearla nuevamente. Sin embargo, agregar más carga en PHP puede no valer la disminución en la carga de MySQL.

¿Alguna idea? ¿Qué harían todos ustedes?

Respuesta

9

UPDATE es mucho más rápido. Cuando UPDATE, los registros de la tabla se están reescribiendo con nuevos datos. Y todo esto debe hacerse nuevamente en INSERT.

Cuando DELETE, los índices deben actualizarse (recuerde, elimina toda la fila, no solo las columnas que necesita modificar) y los bloques de datos pueden moverse (si alcanza el límite PCTFREE). Además, al eliminar y agregar nuevos cambios, se registran los ID en auto_increment, por lo que si esos registros tienen relaciones que se romperían o necesitarían actualizaciones también. Yo iría por UPDATE.

Es por eso que debería preferir INSERT ... ON DUPLICATE KEY UPDATE en lugar de REPLACE.

la anterior es una operación UPDATE en caso de una violación clave, mientras que el segundo es DELETE/INSERT

ACTUALIZACIÓN: He aquí un ejemplo INSERT INTO table (a,b,c) VALUES (1,2,3) ON DUPLICATE KEY UPDATE c=c+1;

Para más detalles leer actualizar documentation

+1

Si actualiza un campo indexado, el índice también se actualiza –

+0

@OMG sí! Olvidé mencionar eso. Bien que lo hiciste ... –

+0

Gracias, eso tiene sentido. Desafortunadamente, cuando se usa un marco basado en ActiveRecord, no siempre es fácil crear una declaración SQL personalizada e incluir "INSERTAR ... EN ACTUALIZACIÓN DE LLAVE DUPLICADA". Si hago eso, tendré que crear una consulta manualmente, y esa consulta probablemente no se traducirá si necesito cambiar el DBMS en el futuro. –

1

Philip, ¿Has intentado hacer declaraciones preparadas? Con declaraciones preparadas, puede agrupar una consulta con diferentes parámetros y llamarla varias veces. Al final de su ciclo, puede ejecutarlos todos con una cantidad mínima de latencia de red. He usado declaraciones preparadas con php y funciona muy bien. Poco más confuso que las declaraciones preparadas de java.

Cuestiones relacionadas