2009-10-19 19 views
5

Tengo un programa C que extrae una gran fuente de datos (20GB de texto sin formato) y genera cargas de INSERT para ejecutar en una tabla en blanco simple (4 columnas enteras con 1 clave primaria). Configuración como una tabla MEMORY, la tarea completa se completa en 8 horas. Después de terminar, existen alrededor de 150 millones de filas en la tabla. Ocho horas es un número completamente decente para mí. Este es un trato de una sola vez.Generando una tabla masiva MySQL de 150M

El problema surge al intentar convertir la tabla MEMORY en MyISAM para que (A) tenga la memoria liberada para otros procesos y (B) los datos no se eliminen cuando reinicie la computadora.

ALTER TABLE memtable ENGINE = MyISAM 

He dejado esta carrera ALTER TABLE consulta por más de dos días, y no se hace. Ahora lo he matado.

Si creo la tabla inicialmente como MyISAM, la velocidad de escritura parece terriblemente mala (especialmente debido al hecho de que la consulta requiere el uso de la técnica ON DUPLICATE KEY UPDATE). No puedo apagar las llaves temporalmente. La mesa se haría más de 1000 veces más grande si tuviera que hacerlo y luego tendría que volver a procesar las claves y, básicamente, ejecutar un GROUP BY en 150,000,000,000 filas. Umm no.

Una de las principales limitaciones a tener en cuenta: la consulta INSERT UPDATE registra si la clave principal (un hash) ya existe en la tabla.

Al comienzo de un intento de utilizar estrictamente MyISAM, obtengo una velocidad aproximada de 1.250 filas por segundo. Una vez que el índice crece, me imagino que esta tasa se acumulará aún más.


Tengo 16 GB de memoria instalados en la máquina. ¿Cuál es la mejor forma de generar una tabla masiva que finalmente termine como una tabla MyISAM indexada en disco?


Aclaración: Hay muchas, muchas actualizaciones que van desde la consulta (INSERT ... ON DUPLICATE KEY UPDATE val=val+whatever). Esto no es, de ninguna manera, un problema de volcado en bruto. Mi razonamiento para probar una tabla MEMORY en primer lugar era para acelerar todas las búsquedas de índice y cambios de tabla que ocurren para cada INSERT.

Respuesta

1

Lamentamos tener el arrojar comentarios sobre usted (último, probablemente).

Acabo de encontrar this article que proporciona un ejemplo de una conversión de una tabla grande de MyISAM a InnoDB, mientras que esto no es lo que está haciendo, utiliza una tabla de memoria intermedia y describe pasar de la memoria a InnoDB de una manera eficiente - Ordenar la tabla en la memoria de la manera en que InnoDB espera que se ordene al final. Si no está vinculado a MyISAM, puede valer la pena verlo ya que ya tiene una tabla de memoria "correcta".

+0

InnoDB estaría bien. Esto es muy inteligente ... me gusta. Gracias por lanzarme comentarios. Lo aprecio. :) – brianreavis

3

Si tiene la intención de convertirlo en una tabla MyISAM, ¿por qué lo está creando en la memoria en primer lugar? Si solo es por la velocidad, creo que la conversión a una tabla MyISAM va a negar cualquier mejora de velocidad que se obtenga al crearla en la memoria para empezar.

Dice que insertar directamente en una tabla "en disco" es demasiado lento (aunque no estoy seguro de cómo está decidiendo que es cuando su método actual está tomando días), es posible que pueda desactivarlo o eliminarlo las restricciones de exclusividad y luego utiliza una consulta DELETE más tarde para restablecer la unicidad y luego volver a habilitar/agregar las restricciones. He usado esta técnica cuando importé en una tabla INNODB en el pasado, y encontré que incluso con la eliminación posterior, en general, era mucho más rápida.

Otra opción podría ser crear un archivo CSV en lugar de las instrucciones INSERT y cargarlo en la tabla usando LOAD DATA INFILE (creo que es más rápido que las inserciones, pero no puedo encontrar una referencia en este momento) o usándolo directamente a través del CSV storage engine, dependiendo de sus necesidades.

+0

He actualizado la pregunta para responder algunas de sus preguntas. He encontrado fuentes que afirman que una inserción de CSV se ejecuta más rápido, pero parece bastante tonto arrojar datos a un archivo CSV de varios gigabytes ** y luego cargarlo a la base de datos. Eso agrega una gran cantidad de E/S de disco duro lento al problema. – brianreavis

+0

Pero estás volcando en un archivo SQL con un conjunto de INSERTS de todos modos, ¿no? No veo cómo un archivo CSV es un sabio de IO diferente. He agregado un párrafo para explicar otro método que puede solucionar el problema de "importar a MyISAM es demasiado lento". –

+0

No puedo eliminar las restricciones de exclusividad. Estoy usando 'ON DUPLICATE KEY UPDATE' para actualizar un registro si la clave principal (un hash) ya existe en el capaz. Si tuviera que eliminar la restricción, la tabla probablemente sería más de 1000 veces el tamaño (y eso no es una exageración). Hay una gran cantidad de ACTUALIZACIONES en curso --- no es solo un basurero en la base de datos. – brianreavis

1

No uso mysql pero uso el servidor SQL y este es el proceso que uso para manejar un archivo de tamaño similar. Primero, vuelco el archivo a una tabla de etapas que no tiene restricciones. Luego identifico y elimino los dups de la tabla de etapas. Luego busco registros existentes que puedan coincidir y pongo el idfield en una columna en la tabla de etapas. Luego actualizo donde la columna del campo de identificación no es nula e inserto donde es nulo. Una de las razones por las que hago todo el trabajo para deshacerme de los dups en la tabla de etapas es que significa menos impacto en la tabla de prod cuando la ejecuto y, por lo tanto, es más rápido al final. Todo mi proceso se ejecuta en menos de una hora (y de hecho hace mucho más de lo que describo ya que también tengo que desnormalizar y limpiar los datos) y afecta las tablas de producción por menos de 15 minutos de ese momento. No tengo que preocuparme por ajustar las restricciones o eliminar los índices ni nada de eso, ya que hago la mayor parte de mi procesamiento antes de llegar a la tabla de prod.

Considere si un proceso similar podría funcionar mejor para usted. También podría usar algún tipo de importación masiva para obtener los datos brutos en la tabla de preparación (llevo alrededor de 16 minutos el archivo de 22 gigas que tengo en escena) en lugar de trabajar fila por fila.

Cuestiones relacionadas