Sé que esta pregunta se ha formulado una y otra vez. Sin embargo, esta es una pregunta muy específica para un escenario muy específico. Espero que puedas ayudarme.Ajuste específico del rendimiento de inserción masiva de MySQL
Ejecuto una base de datos de registro, con aproximadamente 10 tablas. La tabla principal que almacena las entradas de registro reales tiene unos 30 campos, de los cuales 5 se pueden buscar. Diría que la base de datos se ha convertido recientemente en un tamaño moderado, ya que estamos alcanzando los 200 millones de entradas en esa tabla. Otras tablas almacenan datos comunes, de los cuales el más grande tiene 4 campos, todos buscables, con casi 1 millón de entradas. Todas las demás tablas contienen menos de 100 mil registros cada una.
Los insertos vienen en espigas. Obtuve los registros del día anterior en archivos csv (con un formato mediocre) todos los días a las 2 AM, y tengo hasta las 8 AM para insertarlos (alrededor de 20 archivos, 100 mil líneas cada uno) en la base de datos. Luego recibo muy pocas selecciones (tal vez unas 1000 por día) durante el día laboral. Luego enjuague y repita.
Las consultas SELECT son bastante simples, ya que consisten principalmente en una o dos uniones con una o dos instrucciones GROUP BY. Las personas que buscan en esta base de datos quieren resultados inmediatos, por lo que tengo 5 índices de varias columnas en la tabla principal, que ayudan en las búsquedas precisas que tengo, y actualmente, el rendimiento SELECCIONAR es bastante bueno. Ninguna consulta ha tomado más de 0.1 segundos hasta el momento. Hay algunos informes, pero estos demoran alrededor de 10 segundos en generarse, y eso es aceptable.
Actualmente tengo un programa C que escribí para leer los datos de los archivos CSV, limpiarlos e insertarlos en lotes de 1000 filas por consulta INSERT. Estos INSERT no son del todo tontos, porque necesito obtener los datos comunes, ver si ya están en las otras tablas, insertarlo si no es así, y guardarlo en caché, si es así. También me da datos de rendimiento en forma de cuántos registros está insertando por segundo. Este programa es bastante rápido, y sin enviar los datos a la base de datos, obtengo alrededor de 100 mil filas por segundo. Por supuesto, este programa y la base de datos se encuentran en la misma computadora física.
Ahora, los datos que obtengo todos los días están creciendo linealmente, y el rendimiento de los INSERT está disminuyendo logarítmicamente. Los datos de ayer tardaron 5 horas y media en insertarse, en alrededor de 400 inserciones de fila por segundo.
Tengo algunos datos de referencia mediante la inserción de los primeros 1 millón de filas con diferentes configuraciones en una base de datos vacía, y esto es más o menos lo que tengo:
tablas MyISAM: pone en marcha en 1500 filas por segundo, disminuye logarítmicamente abajo a aproximadamente 700 filas por segundo para el momento en que inserta la fila 1 millonésima Tablas InnoDB: igual que MyISAM, solo alrededor de 100 filas por segundo más rápido InnoDB con todos los índices desactivados en la tabla principal: comienza en 2100 filas por segundo, disminuye a 1000 filas por segundo. InnoDB Con índices, con el sistema de archivos montado con reescritura de datos (ext3): igual que InnoDB, solo ligeramente pero casi imperceptiblemente más rápido.
innodb_buffer_pool_size se establece en 1000 MB
Evitar la creación del índice no es una opción, pero es obvio que tiene un gran impacto en el rendimiento. Sin embargo, necesito insertos mucho más rápidos. Como muestran los datos, las inserciones tardarán más a medida que la base de datos crezca, así que a medida que los datos que obtengo sean más grandes cada día, necesito un gran salto en el rendimiento de las inserciones. Si pudiera obtener 10000 inserciones por segundo o más, sería realmente genial.
El monitor del sistema me dice que mi principal consumo de recursos es la E/S de disco, que casi llega al 100% al insertar. Por eso, necesito una forma ultra rápida de insertar datos. Mi límite teórico es el del autobús SATA, pero aún está bastante lejos.El uso de memoria no parece ser tan alto en un 20% (o MySQL no está utilizando la memoria correctamente)
Para lograr esto, es aceptable volver a crear la base de datos en el transcurso de varios días, y luego intercambiar en caliente desde la aplicación del lector, es aceptable cambiar cualquier configuración en el sistema operativo y MySQL, es aceptable agregar memoria si es necesario. Incluso es aceptable cambiar la estructura de la base de datos, si es necesario.
Así que estoy realmente abierto a las ideas aquí. ¿Alguien sabe de algo que pueda ayudarme?
Edición: Actualmente estoy considerando insertar las nuevas filas en una tabla de MEMORIA, y luego hacer una SELECCIÓN EN la tabla real. Con suerte, solo actualizará y purgará el índice una vez que se hayan insertado todas las filas. Voy a probar esto el lunes. ¿Alguien ha intentado algo así antes?
http://stackoverflow.com/q/18033060/632951? – Pacerier