2009-09-01 28 views
7

estoy usando y trabajando en el software que utiliza MySQL como motor de backend (se puede usar a otros como PostgreSQL u Oracle o SQLite, pero esta es la principal aplicación que estamos utilizando). El software fue diseñado de tal manera que los datos binarios queremos acceder se mantiene como BLOB en columnas individuales (cada tabla tiene una BLOB columna, otras columnas tienen números enteros/flotadores para caracterizar la BLOB y una cuerda columna con el hash MD5 BLOB). Las tablas tienen típicamente 2, 3 o 4 índices, uno de los cuales es siempre la columna MD5, que se hace UNIQUE. Algunas tablas ya tienen millones de entradas y han ingresado en el tamaño de varios gigabytes. Mantenemos bases de datos MySQL separadas por año en el mismo servidor (hasta ahora). El hardware es bastante razonable (creo) para aplicaciones generales (un servidor Dell PowerEdge 2U-form).lenta MySQL inserta

MySQL SELECT consultas son relativamente rápido. Hay poca queja allí, ya que estos son (la mayoría de las veces) en modo por lotes. Sin embargo, las consultas INSERT tardan mucho tiempo, lo que aumenta con el tamaño de la tabla (número de filas). Es cierto que esto se debe a que la columna MD5 es del tipo UNIQUE y, por lo tanto, cada INSERT tiene que determinar si cada nueva fila tiene una cadena MD5 correspondiente, ya insertada. Y no es demasiado extraño (creo) si el rendimiento empeora si hay otros índices (no únicos). Pero todavía no puedo dejar de pensar que esta opción de arquitectura de software (sospecho que mantener BLOBs en la fila de la tabla en lugar de disco tiene un impacto negativo significativo) no es la mejor opción. Las inserciones no son críticas, pero es una sensación molesta tener.

¿Alguien tiene experiencia en situaciones similares? ¿Con MySQL, o incluso con otros RDBM (preferiblemente basados ​​en Linux)? ¿Alguna idea que le gustaría proporcionar, tal vez algunas cifras de rendimiento?

Por cierto, el idioma de trabajo es C++ (que envuelve C llama a la API de MySQL).

Respuesta

10

Podría ser un tiempo para la partición horizontal y en movimiento campo BLOB en una tabla separada. En este article en 'A Quick Side Note on Vertical Partitioning', el autor elimina un campo varchar más grande de una tabla y aumenta la velocidad de una consulta sobre el orden de magnitud.

La razón es transversal física de los datos en el disco se convierte en mucho más rápido si hay menos espacio para cubrir, por lo que pasar los campos más grandes aumenta el rendimiento en otros lugares.

También (y probablemente ya lo haga) es beneficioso disminuir el tamaño de la columna de índice a su mínimo absoluto (char (32) en codificación ascii para md5), porque el tamaño de la clave es directamente proporcional al velocidad de su uso.

Si inserciones múltiples a la vez con las tablas InnoDB puede aumentar significativamente la velocidad de insertos envolviéndolos en la transacción y se hacen inserciones mupliple en una consulta:

START TRANSACTION 
INSERT INTO x (id, md5, field1, field2) values (1, '123dab...', 'data1','data2'),(2,'ab2...','data3','data4'),.....; 
COMMIT 
+1

La opción BEGIN TRANSACTION parece ser la solución más directa en este momento. Sin embargo, tengo algunas preguntas, ya que no estoy familiarizado con ella (mantendré RTFM mientras tanto). 1) Dado que la API de MySQL está en C, podría ocurrir que nos equivoquemos e intentemos insertar VALORES que apuntan a nulo. Esto seguramente causará que la aplicación del cliente muera con SEGFAULT. ¿La transacción será "sucia" en este caso? ¿Alguna necesidad de limpiar? ¿Cómo? 2) Estamos usando MyISAM. Cambiar a InnoDB ahora puede ser doloroso y/o peligroso. ¿Conoces el rendimiento de TRANSACTION en MyISAM? Gracias de antemano por su comentario. – jbatista

+1

MhISAM no es transaccional, lo que significa que puede ignorar todo lo que escribí sobre transacciones, sin embargo, la instrucción de inserción con varios cientos o miles de insertos en una consulta también acelerará las cosas en MyISAM. – dimus

+1

OK. ¿Sabes si la sintaxis INSERT INTO impone un límite a la longitud de la cadena de consulta? I.o.w., ¿MySQL acepta una cadena de consulta INSERT INTO con una longitud de (por ejemplo) cientos de millones de caracteres? A mí me huele a problema. – jbatista

1

¿Estás utilizando MyISAM?
AFAIK MyISAM tiene un rendimiento de lectura muy bueno, pero un rendimiento de escritura incorrecto.

InnoDB debe tener una velocidad equilibrada.

+0

Sí, olvidé ese detalle. El servidor que estamos usando usa MyISAM. – jbatista

5

Ver Speed of INSERT Statements. ¿Tiene colisiones MD5 frecuentes? Creo que esto no debería suceder demasiadas veces, así que tal vez puedas usar algo como INSERT ... ON DUPLICATE para manejar las colisiones. Si tiene períodos de inserción específicos, puede disable keys para el momento de la inserción y restaurarlos más tarde. Otra opción es usar replication, usando una máquina maestra para las inserciones y un esclavo para las selecciones.

+0

Gracias por las sugerencias, las investigaré. – jbatista

+1

Desde el enlace de arriba: "Si está insertando muchas filas del mismo cliente al mismo tiempo, use las instrucciones INSERT con múltiples listas VALUES para insertar varias filas a la vez. Esto es considerablemente más rápido (muchas veces más rápido en algunos casos) que utilizando instrucciones INSERT separadas de una sola fila ". Esto llevó mi proceso de inserción de 6K registros de 2.5 minutos a 5 segundos –

1

Cómo encaja sus datos en la memoria RAM? Si no, obtenga más RAM hasta que se vuelva antieconómico (16G suele ser el punto para la mayoría de la gente).

Entonces, ¿sus índices encajan en el buffer de la llave MyISAM?

Si está ejecutando un sistema operativo de 32 bits, no lo haga. Una vez que esté en un sistema operativo de 64 bits, configure el buffer de teclas para que sea aproximadamente 1/3 del ram. La caché del sistema operativo utiliza memoria RAM para almacenar en caché los archivos de datos (lo que hace poco para las inserciones, pero es beneficioso para las selecciones).

Tener tablas de varios gigabytes en MyISAM puede ser un dolor ya que se requieren en el caso de un cierre sucio, muy largo operación (s) de reparación, pero

no lo enchufe motores MySQL sin validación importante de su aplicación, cambiará el comportamiento de muchas maneras (no solo el rendimiento). Afectará el uso del espacio del disco.

1

Hoy también he preguntado algo relacionado question.

Una de las respuestas proporcionadas es considerar el INSERT DELAYED para que entre en la cola de inserción y se maneje cuando el db no está tan ocupado.

+1

Basado en una respuesta en este hilo, he examinado la documentación INSERT DELAYED de MySQL. Afirman que se debe tener cuidado al optar por INSERTAR RETRASADO, ya que puede deteriorar el rendimiento general en las inserciones de un solo cliente en comparación con los INSERTES "normales". – jbatista

+0

ok - Yo mismo no lo vi, aunque también estaba buscando poder acelerar el script que está realizando las inserciones en lugar del rendimiento de la propia inserción – warren

+5

, vale la pena señalar que INSERT DELAYED funciona con MyASAM, pero no InnoDB – dimus

Cuestiones relacionadas