Mi aplicación de análisis genera alrededor de 2 millones de registros durante una sola ejecución. ¿Cuál es la mejor manera de hacer una inserción masiva de estos datos en una base de datos MySQL?

En términos generales, la forma más rápida de mover un lote de datos ASCII sin procesar a cualquier DBMS es a través de técnicas de carga masiva. Como mencionó Joshua Forman, la forma de hacer esto en MySQL es usar LOAD DATA INFILE.

Pero además del uso de carga masiva, hay otras cosas a considerar.

Por ejemplo, si sabe que sus datos están limpios al ingresar, puede deshabilitar las claves primarias, las claves externas, los índices y verificar las restricciones durante la carga, y luego volver a habilitarlas después de la carga. Siempre es más rápido reconstruir índices y restricciones después del hecho que hacer que el DBMS verifique durante una carga de datos.

Pero debo advertirle que solo debe intentar esto si puede garantizar que los datos no violarán la integridad referencial cuando vuelva a activar las restricciones después de la carga. Si no eres POSITIVO porque tu carga de datos no violará las restricciones de integridad referencial, entonces no uses este truco.

Además, mucho depende del sistema que esté cargando, pero si puede evitar desactivar el registro de transacciones durante la carga, también puede obtener algo de rendimiento.

Además de deshabilitar las restricciones y usar técnicas de carga masiva, vale la pena pasar un tiempo pensando en su infraestructura física. La clave para mejorar el rendimiento es eliminar los cuellos de botella. ¿Se pueden almacenar los datos que está cargando en la misma máquina física que la base de datos que está cargando? Si es así, esto podría eliminar la latencia de la red. Por supuesto, si está organizando sus datos en la misma máquina que aloja la base de datos que está cargando, no desea cambiar un cuello de botella por otro. Use un disco para alojar los datos que no contengan ninguno de los espacios de tablas utilizados para almacenar las tablas que está cargando o las tablas del sistema MySQL. (es decir, asegúrese de no causar un cuello de botella de E / S entre la lectura de datos ASCII y la inserción de datos en las tablas de destino)

Definitivamente use LOAD DATA INFILE por la respuesta del usuario de Quora y por el comentario de Brian Rue, divida el archivo en 20-50K filas a la vez (evalúe qué tamaño de ruptura es más rápido; encontrará uno que sea más rápido en función de los tamaños de fila y la E / S del host actuación).

Una sugerencia adicional dependiendo de cómo almacene sus datos diarios es que, si se trata de datos, posiblemente se puedan colocar en una nueva tabla y no agregarse a una tabla existente, eso es más rápido. En iLike teníamos muchos millones de filas de los últimos datos de estadísticas de “reproducción” y “alcance” del artista / álbum / pista que completamos todas las noches en una base de datos. Reemplazaríamos los datos más recientes de la última noche “atómicamente” de la siguiente manera:

  • crear una nueva tabla como la tabla anterior (crear una tabla como barra)
  • CARGAR DATOS DE ARCHIVO los fragmentos en foo, y deshabilitar índices, FK durante la carga
  • renombrar foo a bar, bar a foo
  • soltar foo

esto produce una nueva tabla limpia que se cambia atómicamente de debajo de cualquiera que use la anterior.

En general, el cuello de botella en la inserción masiva estará en el servidor DB

Envío de datos de gran tamaño: como lo sugirió Joshua, puede usar la función de datos de carga es una buena alternativa.

Para un mejor rendimiento en las inserciones masivas, use la función “inserción demorada”: http://dev.mysql.com/doc/refman/