statements query queries multiple clase php mysqli benchmarking mysqli-multi-query

php - queries - Corrección de velocidad/prácticas recomendadas mysqli_multi_query()



php mysqli execute query (2)

No es next_result() culpable, pero sí las consultas. El tiempo que tarda su código en ejecutarse depende del tiempo que tardan las consultas reales en realizarse.

Aunque mysqli_multi_query() devuelve el control bastante rápido, no significa que todas las consultas se mysqli_multi_query() ejecutado en ese momento. Muy al contrario, para cuando mysqli_multi_query() finalizó, solo se ejecutó la primera consulta. Mientras que todas las demás consultas están en cola en el lado mysql para la ejecución asincrónica .

A partir de esto, puede concluir que la llamada a next_result() no agrega ningún tiempo de espera por sí mismo, solo está esperando que finalice la próxima consulta. Y si la consulta en sí misma lleva tiempo, entonces next_result() debe esperar.

Sabiendo que ya puede decir qué camino elegir: si no le importan los resultados, puede cerrar la conexión. Pero, de hecho, será solo barrer la tierra debajo de la alfombra, dejando todas las consultas lentas en su lugar. Por lo tanto, es mejor mantener el bucle next_result() en su lugar (especialmente porque debe verificar los errores / filas afectadas / etc. de todos modos), pero agilizar las consultas.

Entonces, para resolver el problema con next_result() tienes que resolver el problema regular de la velocidad de consulta. Entonces, aquí hay algunas recomendaciones:

  1. Para las consultas de selección, es habitual indexar / explicar analizar, ya explicado en otras respuestas.
  2. Para las consultas DML, especialmente en lotes, existen otras formas:

Hablando del caso de Craig, se parece bastante al problema conocido de la velocidad de innodb escribe. Por defecto, el motor innodb está configurado en un modo muy prudente, donde no se realiza ninguna escritura hasta que el motor asegure que el anterior se terminó con éxito. Por lo tanto, hace que las escrituras sean terriblemente lentas (algo así como solo 10 consultas / seg). La solución común para esto es hacer todas las escrituras a la vez. Para consultas de inserción hay muchos métodos:

  • puedes usar múltiples valores insertar sintaxis
  • puede usar la consulta LOAD DATA INFILE
  • puede envolver todas las consultas en una transacción.

Mientras que para actualizar y eliminar solo la transacción sigue siendo una forma confiable. Entonces, como solución universal, se puede ofrecer una solución de este tipo

$multiSQL = "BEGIN;{$multiSQL}COMMIT;"; $mysqli->multi_query($multiSQL); while ($mysqli->next_result()) {/* check results here */}

Si no funciona / no es aplicable en su caso, le sugiero que cambie mysqli_multi_query() para las consultas individuales que se ejecutan en un bucle, investigue y optimice la velocidad y luego regrese a multi_query.

Me encogí cuando Sebastien dijo que se desconectaba y reconectaba entre cada uso de mysqli_multi_query() @ ¿Puede mysqli_multi_query hacer las afirmaciones de ACTUALIZACIÓN? porque simplemente no parecía la mejor práctica.

Sin embargo, Craig @ mysqli multi_query seguido de consulta indicó en su caso que era más rápido desconectarse y reconectarse entre cada uso de mysqli_multi_query() que emplear mysqli_next_result() .

Me gustaría preguntar si alguien tiene conocimiento de primera mano o evidencia comparativa para sugerir un "punto de corte" aproximado (basado en el volumen de consultas o algo así) cuando un programador debe elegir el método de "nueva conexión" versus "próximo resultado".

También me complace escuchar algunas / todas las preocupaciones no relacionadas con la velocidad. ¿El uso de Craig de una función de conexión tiene alguna relación con la velocidad?

¿Hay una diferencia de velocidad entre la declaración while de Craig?

while ($mysqli->next_result()) {;}

- versus -

una declaración de tiempo que estoy sugiriendo:

while(mysqli_more_results($mysqli) && mysqli_next_result($mysqli));

- versus -

creando una nueva conexión para cada multi_query esperada, antes de ejecutar primero multi_query . Acabo de probar esto, y los dos mysqli_multi_query() s fueron sin error = no close() necesario:

$mysqli1=mysqli_connect("$host","$user","$pass","$db"); $mysqli2=mysqli_connect("$host","$user","$pass","$db");

- versus -

Apertura y cierre entre cada mysqli_multi_query() como Sebastien y Craig:

$mysqli = newSQL(); $mysqli->multi_query($multiUpdates); $mysqli->close();

- versus -

Alguien tiene otra opción para probar en contra?


Para responder tu pregunta:

mira antes de saltar

Espero que tu llamada mysqli_more_results() (la apariencia antes de saltar), no acelere las cosas: si tienes n resultados, harás (2 * n) -1 llamadas a la base de datos, mientras que Craig hace n + 1 .

conexiones múltiples

multi_query ejecuta async , por lo que solo agregará la sobrecarga de conexión.

abrir y cerrar db

Escucha tu sentido común ;-) Pero no pierdas la pista de lo que estás haciendo. Envolver las consultas en una transacción, las hará atómicas . Eso significa que todos fallan o todos tienen éxito . Algunas veces es necesario para que la base de datos nunca entre en conflicto con su universo de discurso. Pero usar transacciones para acelerar, puede tener efectos secundarios no deseados. Considere el caso donde una de sus consultas viola una restricción. Eso hará que la transacción fracase. Lo que significa que, si no fuera una transacción lógica en primer lugar, y la mayoría de las consultas deberían haber tenido éxito, tendrá que averiguar qué salió mal y cuál tendrá que volver a emitirse. Cuesta más dinero en lugar de entregar una aceleración.

Las consultas de Sebastien en realidad parecen que deberían ser parte de una transacción más grande, que contiene la eliminación o actualizaciones de los padres.

En cambio, intenta recordar

no hay cuchara

En sus ejemplos, no hubo necesidad de múltiples consultas. El formulario INSERTAR ... VALORES toma múltiples tuplas para VALORES. Entonces, en lugar de preparar una declaración preparada y envolver sus repetidas ejecuciones en una transacción como Su sentido común sugiere . Podría preparar una sola declaración y hacerla ejecutar y confirmar automáticamente. Según el manual de mysqli esto te ahorra un montón de viajes de ida y vuelta.

Así que crea una declaración SQL del formulario:

INSERT INTO r (a, b, c) VALUES (?, ?, ?), (?, ?, ?), ...

y atar y ejecutarlo. mysqldump --opt lo hace, entonces ¿por qué nosotros no? El manual de referencia de mysql como una sección sobre optimización de declaraciones . Busque en su sección DML para insertar y actualizar consultas. Pero entender por qué --opt hace lo que hace es un buen comienzo.

el valor subestimado de preparar una declaración

Para mí, el valor real de las declaraciones preparadas no es que pueda ejecutarlas múltiples veces, sino que se escape la entrada automática. Para un simple viaje de ida y vuelta extra cliente-servidor, te salvas de la inyección de SQL. La inyección SQL es un punto serio de atención, especialmente cuando se usa multi_query . multi_query le dice a mysql que espere múltiples consultas y las ejecute . Así que no puedes escapar correctamente y te divertirás un poco:

Entonces mi mejor práctica sería:

  1. ¿ Realmente necesito múltiples consultas?
  2. ¡Si lo hago, escapéalos bien o prepáralos !