2011-08-27 11 views
9

Tengo una gran tabla de MySQL (~ 10 millones de filas, 6.5G) que uso para leer & escribir. Es MyISAM y obtengo muchos bloqueos debido al bloqueo de todas las tablas de MyISAM.InnoDB contra MyISAM tiempo de consulta de inserción

Decidí intentar moverme a InnoDB, que se recomienda para tablas de lectura/escritura, y solo bloquea filas específicas en las escrituras.

Después de la conversión, probé las instrucciones de inserción, y resulta que toma ~ 15 veces más (de 0,1 segundos a 1,5 segundos) en la tabla InnoDB que en la tabla MyISAM. ¿Porqué es eso?

Aún no he configurado nada para InnoDB, y planeo agregar particiones también, pero esta cifra todavía es inesperada para mí. Por supuesto, las tablas son las mismas, etc. mismos índices

información adicional de acuerdo a las solicitudes:

2 índices. primary es data_id de tipo Big INT, y user_id no único de tipo varchar (255).

Las inserciones tienen ~ 150 filas juntas que tienen el mismo user_id.

Tamaño de índices: 200 MB en MyISAM, 400 MB en InnoDB

+3

¿Puede mostrarnos los índices? Esa es la causa más probable de tiempos largos de inserción. – wallyk

+0

Tengo 2 índices, data_id que es clave principal y user_id que no es único. Mis insertos son de ~ 150 filas juntas que tienen el mismo user_id (que tiene un índice). – normalppl

+0

, pero ¿cuál es el contenido de cada índice? Si hay un montón de blobs, entonces seguro, será difícil de indexar. Pero si son enteros u otros tipos triviales, entonces es más difícil entender por qué el rendimiento sería malo. – wallyk

Respuesta

5

Un related answer sugiere que la fijación de la variable innodb_flush_log_at_trx_commit a 2 es probable que mejorar el rendimiento cuando la relación de escrituras en lecturas es relativamente alta. Ver the documentation para más.

+0

Solo estoy probando ahora. así que no lee, solo un inserto de 150 filas, quiere descubrirlo primero. – normalppl

+1

Esto hizo una gran diferencia para mí. Insertar 7500 filas sin cambiar 'innodb_flush_log_at_trx_commit' tomó 5 minutos. Cambiarlo a 0 o 2 reduce el mismo INSERT a 3 segundos. – qris

3

Tenga en cuenta la forma en que InnoDB maneja las teclas puede causar problemas. Dado que todo está almacenado en el disco en el orden en que la clave primaria tiene una clave primaria no autoincrementada, puede mover gran parte de la tabla al disco con cualquier inserción (me encontré con este problema cuando tenía una tabla dinámica y utilizaba los identificadores combinados como clave principal). Mover datos en el disco es lento.

También los tamaños de índice pueden ser mucho más grandes con InnoDB porque cada índice también contiene la clave principal. Verifique para asegurarse de que no está corriendo dentro de los límites de memoria.

+0

No esperaba que fuera más rápido, me di cuenta de que se supone que ayuda con muchas lecturas de lectura. Pero si la inserción básica que normalmente realizo toma 15 veces más (de 0.1 segundos a 1.5 segundos), parece que algo no está bien, ¿no? – normalppl

+1

Sí, lo siento, lea como 15% no 15x - es probable que haya algún problema – jisaacstone

4

Creo que, InnoDB implementa un ACID verdadero, y hace un montón de fsync() s para guardar los datos. Y MyISAM no es un ACID verdadero y tiene menos fsync() s.

There are recomendations to kill fsync cuando se necesita para cargar datos de gran tamaño en

If you want to load data into InnoDB quickly: 
* use as large an InnoDB buffer cache as possible 
* make the InnoDB log files as large as possible 
* minimize the number of unique indexes on your tables 
* disable all calls to fsync from InnoDB. You have to hack the code to 
get this, or look at the Google patch. Of course, you only want to run 
in this mode when loading the table. 

And lists says:

MyISAM siempre corre en el modo 'nosync', es decir, que nunca llama a fsync() para eliminar los archivos al disco .

El nosync de InnoDB es útil para probar si algún sistema operativo/computadora es extremadamente lento en fsync(). Pero no debe usarse en un sistema de producción.

El mismo mensaje dice, que InnoDB veces usa otro método de sincronización:

Entonces InnoDB utiliza fsync() para volcar tanto los datos y archivos de registro.Si O_DSYNC es especificado, InnoDB usa O_SYNC para abrir y purgar los archivos de registro, pero usa fsync() para enjuagar los archivos de datos. Si se especifica O_DIRECT (disponible en algunas versiones de Linux a partir de MySQL-4.0.14), InnoDB usa O_DIRECT para abrir los archivos de datos , y usa fsync() para eliminar los datos y los archivos de registro. Tenga en cuenta que InnoDB no usa fdatasync() u O_DSYNC porque ha habido problemas con en muchos sabores de Unix.

2

En primer lugar, su prueba no es válida, ya que el aumento de la velocidad de bloqueo de filas contra bloqueo a nivel de tabla viene cuando hay concurrencia! Con solo 1 inserciones de fabricación de hilo, tiene 1 bloqueo/desbloqueo por inserción en ambos casos, y las inserciones no esperan que se suelte el bloqueo de nivel de tabla.

Segundos, según lo declarado por JIStone, la clave primaria no secuencial es el asesino de rendimiento para las inserciones, cuando el tamaño de la tabla es más grande que el grupo de búferes.

En tercer lugar, el tamaño del grupo de búferes es uno de los ajustes más importantes en InnoDB. Haga lo más posible (la configuración recomendada es 80% de la RAM disponible).

A continuación, según lo indicado por @wallyk, innodb_flush_log_at_trx_commit tiene un papel crucial para la velocidad de las operaciones de E/S.

A continuación, son importantes el innodb_log_file_size y el innodb_buffer_file_size.

A continuación, tenga en cuenta que, dado que tiene 2 índices únicos, antes de que InnoDB pueda insertar la fila, debe verificar la existencia del valor en los índices, y sus índices son grandes.

Sin tener detalles sobre la tabla y los índices, no puedo darle más consejos, pero tenga en cuenta que ningún motor de almacenamiento es una panacea, y aunque a menudo puede ganar mucha velocidad simplemente cambiando el motor de almacenamiento, agregando índice, o ajustando una variable, en sistemas a gran escala las cosas son más complejas que esto. Pero, como dije, no debe comparar la velocidad de la inserción bruta en una prueba aislada, debe realizar la prueba lo más cerca posible de la aplicación real.

actualización: un consejo más En MyISAM e InnoDB, multi-insert (insertar en los valores .... (...), (...), (...)) es más rápido. Además, en InnoDB puede hacer insertos en la transacción, lo que desactiva la actualización de índices no exclusivos antes de que finalice la transacción, y también es más rápido (pero no realiza grandes transacciones, ya que esto realmente ralentizará el nivel de aislamiento utilizado y la forma en que funciona el versionado de filas).

Cuestiones relacionadas