2012-03-09 20 views
5

Tengo una aplicación PHP/MySql que crece rápidamente y escribe mucho, inserta nuevas filas a razón de una docena o más por segundo en una tabla INNODB de varios millones de filas.MySql INSERT contra PHP file_put_contents

Empecé a usar las instrucciones INSERT en tiempo real y luego me mudé a PHP_subs_contents para escribir entradas en un archivo y CARGAR DATOS INFILE para obtener los datos en la base de datos. ¿Cuál es el mejor enfoque?

¿Hay alguna alternativa que deba considerar? ¿Cómo puedo esperar que los dos métodos manejen las colisiones y el aumento de la carga en el futuro?

Gracias!

+0

Una alternativa es escribir en una tabla secundaria, luego hacer una 'inserción en ... seleccionar de' a granel en la tabla principal, si las escrituras en la tabla principal están llegando a ser un problema. –

Respuesta

3

Piense en LOAD DATA INFILE como un método por lotes de inserción de datos. Elimina la sobrecarga de activar una consulta de inserción para cada instrucción, por lo tanto, es mucho más rápido. Sin embargo, pierde parte del control al manejar errores. Es mucho más fácil manejar un error en una sola consulta de inserción en comparación con una fila en el medio de un archivo.

+0

Puede usar la inserción de sintaxis en valores de tabla (fila1), (fila2), ..., (filaN); para insertar tantas filas como desee con una sola consulta. También puede agregar "... en actualización de clave duplicada ..." para especificar cómo manejar las colisiones de clave únicas – atxdba

+0

@atxdba Esa es una idea horrible en insertos grandes. – feketegy

+0

@feketegy Horrible ¿cómo? ¿Actuación? http://tinyurl.com/7jmzbcp Es una publicación de SO que explica cómo es mejor y preferido. Por supuesto, no desea cargar varios gigs de datos en un solo inserto, pero al hacer una declaración general indefinida de que es horrible, simplemente está mal. Incluso mysqldump creará inserciones por lotes de forma predeterminada. Si está diciendo que para los grandes conjuntos de datos de carga de datos puede ser mejor, no voy a discutir eso. Realmente solo estaba señalando la sintaxis disponible. – atxdba

0

La forma en que tratamos nuestros insertos es enviarlos a un sistema de cola de mensajes como ActiveMQ. A partir de ahí, tenemos una aplicación separada que carga las inserciones utilizando LOAD DATA INFILE en lotes de aproximadamente 5000. El manejo de errores aún puede realizarse con el archivo infile, pero procesa las inserciones mucho más rápido. Si configurar una cola de mensajes está fuera del alcance de su aplicación, no hay ninguna razón para que file_put_contents no sea una opción aceptable, especialmente si ya está implementado y funciona correctamente.

Además, es posible que desee probar la desactivación de índices durante las escrituras para ver si eso mejora el rendimiento.

+0

Buena nota sobre la desactivación de índices: gracias – user1259956

+0

Otro punto a considerar es dónde se encuentra el cuello de botella para su sistema en particular. Intenta usar iostat y vmstat para determinar dónde están tus ralentizaciones y dónde debes enfocar tus esfuerzos. Dependiendo de lo que esté haciendo con sus datos, existen muchas soluciones para el almacenamiento, algunas de ellas mucho más rápidas si no son compatibles con ACID. – RumpRanger

0

No parece que deba usar innoDB. De todos modos, una docena de insertos por segundo no debería ser problemático ni siquiera para el hardware defectuoso, a menos que, posiblemente, su modelo de datos sea muy complejo, pero para eso, LOAD DATA INFILE es muy bueno porque, entre otras cosas, reconstruye los índices solo una vez, a diferencia de en cada inserción. Entonces, usar archivos es un enfoque decente, pero asegúrese de abrirlos en el modo de solo agregar.

a largo plazo (1k + de escrituras/s), consulte otras bases de datos, particularmente cassandra para escribir aplicaciones pesadas.

+0

La indexación estaba en mi mente también. ¿Qué va a ser más rápido por escritura, añadiendo a un archivo plano o insertándolo en una base de datos? ¿Cómo manejarían las solicitudes simultáneas? – user1259956

+0

realmente depende, necesita ejecutar pruebas y resolverlo para su entorno. Adjuntar a un archivo es solo atómico si mantiene los datos dentro de un límite (creo que es 4K en Linux), o/w tendrá problemas con la concurrencia – miki

2

Dependiendo de si puede permitirse que los datos insertados por PHP no estén disponibles al instante en la tabla, entonces INSERT DELAYED podría ser una opción.

MySQL aceptará los datos que se van a insertar y se ocupará de la inserción más adelante, poniéndolo en una cola. Por lo tanto, esto no bloqueará su aplicación PHP, mientras que MySQL asegura que los datos se inserten más adelante.

As it says in the manual:

Otra importante ventaja de usar INSERT DELAYED es que las inserciones de muchos clientes se agrupan y se escriben en un bloque. Esto es mucho más rápido que realizar muchas inserciones por separado.

he utilizado esto para el registro de datos en una pérdida de datos no es fatal, pero si quieres ser protegidos de servidor se bloquea cuando no se habían insertado los datos de INSERT DELAYED, usted podía mirar en replicar los cambios de distancia de una máquina esclava dedicada.

0

si va por la ruta de inserción sql, ajuste las instrucciones de ejecución de pdo en una transacción. hacerlo acelerará en gran medida el proceso.