MySQL LOAD DATA INFILE se ralentiza en un 80% después de algunos conciertos de entrada con el motor InnoDB

14

Estoy cargando un archivo de 100GB a través de LOAD DATA INFILE. He tenido buen éxito con MyISAM, unas pocas horas y listo.

Lo estoy intentando ahora usando InnoDB. La carga comienza rápidamente a más de 10 MB / s (ver el crecimiento del archivo de la tabla, file_per_tableestá activada).

Pero después de aproximadamente 5 GB de datos, se ralentiza al rango de 2-4 MB / seg., Cuando obtengo más de 20 GB, disminuía alrededor de 2 MB / seg.

El tamaño de las agrupaciones de almacenamiento intermedio de InnoDB es 8G. Y he hecho lo siguiente antes de ejecutar el comando LOAD DATA INFILE:

SET @@session.sql_log_bin=0;
SET autocommit=0;
SET unique_checks=0;
SET foreign_key_checks=0;
alter table item_load disable keys;
//Run LOAD DATA INFILE....

No puedo ver la razón por la cual está comenzando bien y disminuyendo con el tiempo.

Además, usando la misma configuración, ejecuté el mismo comando LOAD DATA INFILE con la tabla usando InnoDB y MyISAM y un conjunto de datos de prueba de 5GB, MyISAM fue 20 veces más rápido:

InnoDB:

mysql> LOAD DATA CONCURRENT LOCAL INFILE '/tmp/item' REPLACE INTO TABLE item_load;
Query OK, 2630886 rows affected, 6 warnings (21 min 25.38 sec)
Records: 2630886  Deleted: 0  Skipped: 0  Warnings: 6

MyISAM:

mysql> LOAD DATA CONCURRENT LOCAL INFILE '/tmp/item' REPLACE INTO TABLE item_load;
Query OK, 2630886 rows affected, 6 warnings (1 min 2.52 sec)
Records: 2630886  Deleted: 0  Skipped: 0  Warnings: 6

¿Algo más que deba considerar intentar? El motor MyISAM puede mantener la velocidad de carga mucho mejor.


Detalles adicionales:

  • He intentado cargar los archivos individualmente, no hay diferencia.

  • Por cierto, tengo 150 archivos de 500 MB cada uno, dentro de cada archivo se ordenan las claves.

  • Después de obtener 40 GB durante la noche, 12 horas después, la velocidad de carga se redujo a 0.5 MB / seg, lo que significa que la operación es, prácticamente hablando, imposible.

  • No he encontrado ninguna otra respuesta a preguntas similares en otros foros, me parece que InnoDB no admite cargar grandes cantidades de datos en tablas de más de unos pocos GB.

David Parks
fuente

Respuestas:

7

OBSERVACIÓN # 1

Me di cuenta de que te apagaste autocommit. Eso acumulará tantos datos en ibdata1. ¿Por qué?

Hay siete (7) clases de información que se almacenan en ibdata1:

  • Páginas de datos para tablas InnoDB
  • Páginas de índice para tablas InnoDB
  • Diccionario de datos
  • Buffer de doble escritura
    • Red de seguridad para prevenir la corrupción de datos
    • Ayuda a evitar el sistema operativo para el almacenamiento en caché
  • Insertar almacenamiento intermedio (racionaliza los cambios en los índices secundarios)
  • Segmentos de reversión
  • Deshacer registros
  • Haga clic aquí para ver una representación pictórica de ibdata1

Parte de esta información se hace visible para ciertas transacciones dependiendo del nivel de aislamiento. Dichas acciones podrían producir bloqueos de teclas primarios no deseados y muchos datos fantasmas . A medida que estas dos cosas aumentan, debe esperar una desaceleración justa.

Recomendación: deje la confirmación automática activada

OBSERVACIÓN # 2

Veo que tienes esto:

alter table item_load disable keys;

DISABLE KEYS no funciona con InnoDB . Aquí es por qué:

  • MyISAM: DISABLE KEYSsimplemente apaga la actualización del índice secundario para la tabla MyISAM. Cuando se inserta en masa en una tabla MyISAM con las teclas deshabilitadas, se produce una carga rápida de la tabla junto con una construcción de la CLAVE PRIMARIA y todos los índices únicos. Cuando ejecuta ENABLE KEYS, todos los índices secundarios se crean linealmente en la tabla y se agregan a.MYD .
  • InnoDB: como se muestra en la imagen interna de InnoDB, el sistema tablespave ibdata1tiene una estructura dedicada a las Inserciones de índice secundario. En la actualidad, no existe ninguna disposición para manejar índices de la misma manera que MyISAM.

Para ilustrar esto, tenga en cuenta mi intento de ejecutar DISABLE KEYS en una tabla InnoDB en MySQL

mysql> show create table webform\G
*************************** 1. row ***************************
       Table: webform
Create Table: CREATE TABLE `webform` (
  `nid` int(10) unsigned NOT NULL,
  `confirmation` text NOT NULL,
  `confirmation_format` tinyint(4) NOT NULL DEFAULT '0',
  `redirect_url` varchar(255) DEFAULT '<confirmation>',
  `status` tinyint(4) NOT NULL DEFAULT '1',
  `block` tinyint(4) NOT NULL DEFAULT '0',
  `teaser` tinyint(4) NOT NULL DEFAULT '0',
  `allow_draft` tinyint(4) NOT NULL DEFAULT '0',
  `submit_notice` tinyint(4) NOT NULL DEFAULT '1',
  `submit_text` varchar(255) DEFAULT NULL,
  `submit_limit` tinyint(4) NOT NULL DEFAULT '-1',
  `submit_interval` int(11) NOT NULL DEFAULT '-1',
  PRIMARY KEY (`nid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

mysql> alter table webform disable keys;
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> show warnings;
+-------+------+-------------------------------------------------------------+
| Level | Code | Message                                                     |
+-------+------+-------------------------------------------------------------+
| Note  | 1031 | Table storage engine for 'webform' doesn't have this option |
+-------+------+-------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> select version();
+------------+
| version()  |
+------------+
| 5.5.27-log |
+------------+
1 row in set (0.00 sec)

mysql>

OBSERVACIÓN # 3

Notó que MyISAM se carga 20 veces más rápido que InnoDB. ¿Te gustaría que sea más como 24-25 veces más rápido? Luego ejecute lo siguiente:

ALTER TABLE item_load ROW_FORMAT=Fixed;

Esto acelerará INSERTs veces 20-25% sin ningún otro cambio DDL . Efecto secundario: la tabla MyISAM puede crecer 80% -100% de tamaño, posiblemente más grande.

También podría ejecutar esto en una tabla InnoDB, pero el comportamiento compatible con ACID y el MVCC de InnoDB seguirían siendo el cuello de botella de su rendimiento, especialmente si se escriben campos VARCHAR de aumento significativo ibdata1.

RolandoMySQLDBA
fuente
Las primeras 2 observaciones fueron cosas que intenté agregar para solucionar el problema después de que lo noté por primera vez, mi primer intento fue naturalmente dejar innodb solo (solo apague el registro de bin). En la tercera observación, el tamaño de mis datos es muy variable en longitud, ¿supongo que esto será un problema? Siento que solo necesito mantener esta mesa myisam.
David Parks
6

La respuesta final a esta pregunta fue no usar InnoDB para una tabla de referencia masiva. MyISAM está gritando rápidamente, casi el rendimiento total de la velocidad del disco para toda la carga, InnoDB se atasca. MyISAM es simple, pero en este caso también lo son los requisitos de esta tabla. Para una tabla de referencia simple con cargas masivas sobre LOAD DATA INFILE, MyISAM es el camino a seguir, hasta ahora todo bien.

Pero tenga en cuenta que si ejecuta las tablas MyISAM e InnoDB, tendrá que considerar la asignación de memoria para 2 mecanismos de almacenamiento en caché, cada motor tiene su propio almacenamiento en caché único que necesita una asignación de memoria separada.

David Parks
fuente
5

Puede intentar dividir sus archivos de entrada en fragmentos más pequeños.

Yo personalmente uso http://www.percona.com/doc/percona-toolkit/2.1/pt-fifo-split.html para esto.

¿Qué sucede si obtiene un bloqueo de tabla por tabla durante la importación? Tal vez el bloqueo de nivel de fila de InnoDB lo ralentiza (MyISAM usa un bloqueo de tabla).

También puede leer aquí para obtener más ideas: http://derwiki.tumblr.com/post/24490758395/loading-half-a-billion-rows-into-mysql

bnadland
fuente
Mis archivos ya están en fragmentos de 500 MB, los estaba canalizando a través de una sola tubería con nombre para facilitar la carga, pero intentaré este enfoque ahora.
David Parks
Al no ver ninguna diferencia aquí, veo rápidamente que la velocidad cae de la expansión de 11 MB / s del archivo DB a 6 MB (después de aproximadamente 2 GB) de datos y continúa bajando. Estoy cargando todos los archivos en un bucle for, llamadas mysql separadas.
David Parks
El primer archivo cargado en 54s, 2do en 3m39s, 3ro en 3m9s, 4m7s, 5m21s, y así sucesivamente. Todos los archivos tienen aproximadamente el mismo tamaño.
David Parks
2

Si su PK no es AUTO_INCREMENT o los datos en el archivo csv no están ordenados en PK, podría estar afectando el rendimiento de la carga de datos. Dado que la tabla en MySQL es un índice, por lo tanto, todos los datos se almacenan en orden ordenado, si el valor PK no está en AUTO_INCREMENT, entonces MySQL tiene que hacer muchos cambios de datos para obtener los datos almacenados en orden ordenado. Esta es la razón de una carga de datos más lenta cuando el tamaño de la tabla comienza a crecer.

Estoy cargando un archivo csv de 91GB con PK en AUTO_INCREMENT usando LOAD DATA INFILE y no veo ninguna caída en mi rendimiento. Estoy obteniendo insertos de 140K a 145K por segundo. Usando Percona MySQL 5.6.38

KKYadav
fuente