2009-11-24 14 views

Respuesta

221

http://dev.mysql.com/doc/refman/5.0/en/insert-speed.html

El tiempo requerido para insertar una fila está determinada por los siguientes factores, donde los números indican proporciones aproximadas:

  • de conexión: (3)
  • Envío de consulta al servidor : (2)
  • Consulta de análisis: (2)
  • Inserción de la fila: (1 × tamaño de la fila)
  • índices Inserción: (1 × número de índices)
  • de cierre: (1)

De esto debería ser obvio, que el envío de un comunicado grande le ahorrará una sobrecarga del 7 por inserción declaración, que al leer más el texto también dice:

Si está insertando muchas filas del mismo cliente al mismo tiempo, utilice 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 el uso de instrucciones INSERT separadas de una sola fila.

+12

¿Cómo se aplica esta respuesta si múltiples INSERT individuales están dentro de la misma transacción de base de datos? – Pinch

+1

Cuántas filas puedo insertar a la vez usando la instrucción de inserción única. ¿Me permite insertar 10000 filas a la vez? –

+2

@Pinch El uso de una transacción mientras hace ~ 1.5k upserts (insertar/actualizar) disminuyó el tiempo que la operación tomó de ~ 1.5 segundos a ~ 0.2 segundos. O en otras palabras, lo hizo un 86% más rápido en comparación con los insertos de una sola fila. Maldita sea. – fgblomqvist

5

enviar tantas inserciones a través del cable al mismo tiempo como sea posible. La velocidad de inserción real debe ser la misma, pero verá mejoras en el rendimiento a partir de la reducción de la sobrecarga de la red.

4

En general, el menor número de llamadas a la base de datos la mejor (es decir, más rápido, más eficiente), a fin de tratar de codificar los insertos de tal manera que se minimiza accede a la base de datos. Recuerde que, a menos que use un grupo de conexiones, cada acceso al databse tiene que crear una conexión, ejecutar el sql y luego cortar la conexión. ¡Bastante un poco por encima!

+0

lo que si se utiliza la conexión persistente? – dusoft

+5

Todavía hay gastos generales. El tiempo de tránsito solo (hacia y desde cada inserción por separado) será rápidamente perceptible si está haciendo miles de insertos. –

2

En general, las inserciones múltiples será más lento debido a la sobrecarga de conexión. Hacer varias inserciones a la vez reducirá el costo de la carga por inserción.

Dependiendo del lenguaje que está utilizando, que posiblemente puede crear un lote en su idioma/secuencias de comandos de programación antes de ir a la db y añadir cada inserto al lote. Entonces podría ejecutar un lote grande usando una operación de conexión. Here's un ejemplo en Java.

12

Un factor importante será si está utilizando un motor transaccional y si tiene activado el compromiso automático.

confirmación automática está activada por defecto y es probable que desee dejar actuar; por lo tanto, cada inserción que haces hace su propia transacción. Esto significa que si hace una inserción por fila, va a comprometer una transacción para cada fila.

Suponiendo un solo hilo, eso significa que el servidor necesita sincronizar algunos datos en un disco para cada fila. Necesita esperar a que los datos lleguen a una ubicación de almacenamiento persistente (es de esperar que el RAM de respaldo de la batería en su controlador RAID). Esto es intrínsecamente lento y probablemente se convierta en el factor limitante en estos casos.

Por supuesto, supongo que está utilizando un motor transaccional (generalmente innodb) Y que no ha modificado la configuración para reducir la durabilidad.

También estoy asumiendo que está utilizando un solo hilo para hacer estas inserciones. El uso de varios subprocesos complica un poco las cosas porque algunas versiones de MySQL tienen un grupo de trabajo comprometido en innodb, lo que significa que varios subprocesos pueden compartir una sola escritura en el registro de transacciones, lo que es bueno porque significa menos sincronizaciones con el almacenamiento persistente. .

Por otro lado, el resultado es que REALMENTE QUIERE UTILIZAR insertos de varias hileras.

Existe un límite sobre el cual se vuelve contraproducente, pero en la mayoría de los casos es de al menos 10,000 filas. Entonces, si los lotes hasta 1.000 filas, probablemente estés a salvo.

Si está utilizando MyISAM, hay muchas otras cosas, pero no le aburriré con eso. Paz.

+0

¿Hay alguna razón por la que se vuelva contraproducente después? ¿un punto? Lo he visto suceder antes también, pero no estaba seguro de por qué. –

+1

¿Sabes si hay algún punto en el lote de las inserciones de MySQL cuando ** usa transacciones **. Me pregunto si puedo ahorrarme el problema de tener que generar el comando SQL multivaluado si mi biblioteca subyacente (Java JDBC - mysql-connector-java-5.1.30) no se está comprometiendo hasta que yo lo diga. – RTF

3

Es posible que desee:

  • Compruebe que el auto-commit está fuera
  • Abrir conexión
  • enviar varios lotes de inserciones en una sola transacción (tamaño de alrededor de 4.000 a 10.000 filas que se ve?)
  • Cerrar conexión

Dependiendo de qué tan bien sus escalas de servidor (su forma definitiva bien con PostgreSQl, Oracle y MSSQL), haga lo anterior con varios subprocesos y conexiones múltiples.

118

Sé que estoy respondiendo a esta pregunta casi dos años y medio después de que me lo pidieron, pero solo quería proporcionar algunos datos concretos de un proyecto en el que estoy trabajando ahora que muestra que efectivamente hace varios bloques de VALOR por inserción es MUCHO más rápido que las sentencias INSERT secuencia de un solo bloque secuencial.

El código que escribí para este benchmark en C# utiliza ODBC para leer datos en la memoria de una fuente de datos MSSQL (~ 19,000 filas, todos se leen antes de que comience la escritura), y el conector MySql .NET (Mysql.Data. *) cosas para INSERTAR los datos de la memoria en una tabla en un servidor MySQL mediante declaraciones preparadas. Fue escrito de tal manera que me permitiera ajustar dinámicamente el número de bloques de VALOR por INSERT preparado (es decir, insertar n filas a la vez, donde podría ajustar el valor de n antes de una ejecución). También realicé la prueba varias veces para cada n.

Hacer bloques VALUE solos (por ejemplo, 1 fila a la vez) tomó 5.7 - 5.9 segundos para ejecutarse. Los otros valores son como sigue:

2 filas a la vez: 3.5 - 3.5 segundos
5 filas a la vez: 2.2 - 2.2 segundos
10 filas a la vez: 1.7 - 1.7 segundos
50 filas en un tiempo: 1.17 - 1.18 segundos
100 filas a la vez: 1.1 - 1.4 segundos
500 filas a la vez: 1.1 - 1.2 segundos
1000 filas a la vez: 1.17 - 1.17 segundos

Así que sí, incluso agrupar 2 o 3 escrituras proporciona una mejora dramática en la velocidad (corte en tiempo de ejecución por un factor de n), hasta llegar a algo entre n = 5 yn = 10, en cuyo punto la mejora disminuye notablemente, y en algún punto del rango n = 10 a n = 50 la mejora se vuelve insignificante.

Espero que ayude a la gente a decidir (a) si usar la idea de multiplicación múltiple, y (b) cuántos bloques de VALOR crear por afirmación (suponiendo que quiere trabajar con datos que pueden ser lo suficientemente grandes para empujar la consulta el tamaño máximo de consulta para MySQL, que creo que es de 16 MB de forma predeterminada en muchos lugares, posiblemente más grande o más pequeño según el valor de max_allowed_packet establecido en el servidor.)

+0

Solicitud de aclaración: es su tiempo "segundos por fila" o "segundos en total". – EngrStudent

+2

Total de segundos, por lo que los segundos por fila son los divididos entre las ~ 19,000 filas. Aunque es un número pequeño, quizás las filas/segundo sean una mejor medida si está buscando un número fácilmente comparable. –

1

Las comprobaciones de restricción de desactivación hacen que las inserciones sean mucho más rápidas. No importa que tu mesa lo tenga o no. Por ejemplo prueba de desactivación de claves externas y disfrutar de la velocidad:

SET FOREIGN_KEY_CHECKS=0; 
3

MySQL 5.5 Una instrucción SQL de inserción tomó ~ 300 ~ a 450 ms. mientras que las siguientes estadísticas son para enmiendas de inserción múltiple en línea.

(25492 row(s) affected) 
Execution Time : 00:00:03:343 
Transfer Time : 00:00:00:000 
Total Time  : 00:00:03:343 

diría en línea es camino a seguir :)

Cuestiones relacionadas