2010-09-30 16 views
7

Estoy tratando de obtener una mejor comprensión sobre la velocidad de inserción y los patrones de rendimiento en mysql para un producto personalizado. Tengo dos tablas a las que agrego nuevas filas. Las dos tablas se definen de la siguiente manera:Desaceleración de la velocidad de inserción a medida que la tabla crece en mysql

CREATE TABLE events (
added_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, 
id BINARY(16) NOT NULL, 
body MEDIUMBLOB, 
UNIQUE KEY (id)) ENGINE InnoDB; 

CREATE TABLE index_fpid (
fpid VARCHAR(255) NOT NULL, 
event_id BINARY(16) NOT NULL UNIQUE, 
PRIMARY KEY (fpid, event_id)) ENGINE InnoDB; 

y guardo la inserción de nuevos objetos a ambas tablas (para cada nuevo objeto, i insertar la información relevante para ambas tablas en una sola transacción). Al principio, obtengo alrededor de 600 inserciones/seg, pero después de ~ 30000 filas, obtengo una desaceleración significativa (alrededor de 200 inserciones/seg), y luego una desaceleración más lenta, pero aún notable.

Veo que a medida que la tabla crece, los números de espera de IO se vuelven cada vez más altos. Mi primer pensamiento fue la memoria tomada por el índice, pero esos se hacen en una máquina virtual que tiene 768 Mb, y está dedicada a esta tarea sola (2/3 de memoria no se utilizan). Además, tengo dificultades para ver 30000 filas que toman tanta memoria, incluso más los índices (todo el directorio de datos mysql < 100 Mb de todos modos). Para confirmar esto, asigné muy poca memoria a la VM (64 Mb), y el patrón de desaceleración es casi idéntico (es decir, aparece la disminución después de la misma cantidad de inserciones), así que sospecho algunos problemas de configuración, especialmente porque soy relativamente nuevo bases de datos.

El patrón se ve de la siguiente manera: alt text

Tengo un script en Python autónomo que reproduce el problema, que pueda poner a disposición si eso es útil.

Configuración:

  • Ubuntu 10.04, 32 bits que se ejecutan en KVM, 760 Mb que se le asignen.
  • MySQL 5.1, fuera de la configuración de la caja con los archivos separados para las tablas

[EDIT]

muchas gracias a Eric Holmberg, que clavó. Aquí están los gráficos después de reparar el innodb_buffer_pool_size a un valor razonable: alt text

+0

El problema es la posibilidad de escribir en el disco, virtual o no. –

+0

No estoy seguro de entender lo que quiere decir: entiendo que lleva tiempo escribir en el disco, pero eso no explica la desaceleración a medida que la mesa crece. –

Respuesta

8

Edite su archivo /etc/mysql/my.cnf y asegúrese de asignar suficiente memoria al grupo de búferes de InnoDB. Si se trata de un servidor dedicado, probablemente pueda usar hasta el 80% de la memoria de su sistema.

# Provide a buffer pool for InnoDB - up to 80% of memory for a dedicated database server 
innodb_buffer_pool_size=614M 

Las claves primarias son B Árboles por lo inserciones siempre llevará tiempo O (logN) y una vez que se quede sin memoria caché, que se iniciará el canje como locos. Cuando esto sucede, es probable que desee dividir los datos para mantener la velocidad de inserción. Consulte http://dev.mysql.com/doc/refman/5.1/en/partitioning.html para obtener más información sobre el particionamiento.

¡Buena suerte!

+0

Eso fue todo, muchas gracias. Actualizaré los gráficos para mostrar la diferencia, es bastante llamativo. Gracias por el consejo de partición: ya estaba investigando la partición, pero no quería ir allí sin entender primero este problema. –

+2

Gracias por hacer un esfuerzo adicional para actualizar los gráficos: ¡el segundo conjunto se ve genial! –

1

Es posible que sus índices solo necesiten ser analizados y optimizados durante la inserción, que gradualmente se irán formando a medida que avanza. La otra opción, por supuesto, es deshabilitar los índices completamente cuando los está insertando y reconstruirlos más tarde, lo que debería proporcionar un rendimiento más consistente.

Great link about insert speed.

ANALYZE. OPTIMIZE

+0

Solo hay dos índices: la clave principal y una restricción única. Ambos hacen cumplir valores únicos. A menos que haya eliminaciones, no hay nada que mantener. –

+0

No creo que pueda desactivar el índice (en mi aplicación, necesito hacer las inserciones disponibles tan pronto como se escriben, y las inserciones entran en "tiempo real", no es un procesamiento por lotes). –

+0

Confío en ti OMG, si dices que es así espero ansiosamente tu respuesta para poder aprender. –

0

La verificación de que la inserción no infringe una restricción de clave lleva tiempo, y ese tiempo aumenta a medida que la tabla aumenta. Si está interesado en el rendimiento a toda máquina, usar LOAD DATA INFILE mejorará considerablemente la velocidad de su inserción.

+0

Esperaba que la inserción disminuyera a medida que la tabla crezca (debido al costo de registro (N) de las actualizaciones de índices). Pero la desaceleración aquí es causada por un aumento de IO, si creo que el% de espera, y eso es inesperado (ya que tengo un conjunto de datos lo suficientemente pequeño como para caber completamente en la memoria). Además, mis gráficos no muestran un registro (N) más lento. –

+0

Es algo raro que todo su conjunto de datos se ajuste a la memoria, pero me alegra que su problema esté resuelto. 'LOAD DATA INFILE' todavía le mostrará mejoras de rendimiento adicionales si sus requisitos son tales. –

Cuestiones relacionadas