Diferencia entre consultas con búfer y sin búfer

5 minutos de lectura

avatar de usuario
texalar

Siempre tuve la impresión de que la diferencia, en términos simples, entre las consultas con y sin búfer de PHP/MySQL es que el búfer (el valor predeterminado) carga todos los datos en la variable del conjunto de resultados y entonces puede comenzar a usarlos mientras que sin búfer carga una fila a la vez.

di que corriste SELECT * FROM sometable y luego lo hizo $result = $db->query($query);, $result contendría todas las filas e información complementaria, como el número de filas. Entonces, si lo hizo en una base de datos de 100 MB, esperaría $result ocuparía ~100 MB si no hubiera índices allí).

Sin embargo, me encontré con esta pregunta de desbordamiento SO, parte de la cual dice consultas almacenadas en búfer:

[The] El resultado contendrá algún búfer de filas que depende de la implementación. Pueden ser 100 filas o más o menos. Se devuelven todas las columnas para cada fila; A medida que obtenga más filas, eventualmente el cliente le pedirá al servidor más filas. Esto puede ser cuando se agota el cliente o puede hacerse de forma preventiva.

¿Es esto correcto, realmente todavía hay algo de almacenamiento en búfer? Si ese es el caso, ¿generalmente no debemos preocuparnos de que PHP se quede sin memoria cuando se trata de grandes conjuntos de resultados? Es extraño porque he estado ejecutando algunas consultas almacenadas en búfer de prueba en una tabla de prueba de 40 MB y PHP siempre informa un uso máximo de memoria de ~ 5 MB.

Finalmente, como regla general, ¿cuándo se elige sin búfer en lugar de con búfer? ¿Puede proporcionar un ejemplo?

(Por cierto, estoy usando MySQLi. Supongo que el principio es el mismo).

He leído un poco más ahora y estoy aún más confundido. Sobre http://php.net/manual/en/mysqli.quickstart.statements.php dice

Los resultados de la ejecución de la instrucción On After se pueden recuperar de una vez para que el cliente los almacene en el búfer o para que se lean fila por fila. El almacenamiento en búfer del conjunto de resultados del lado del cliente permite que el servidor libere los recursos asociados con los resultados de la declaración lo antes posible. En términos generales, los clientes son conjuntos de resultados que consumen lentamente. Por lo tanto, se recomienda utilizar conjuntos de resultados almacenados en búfer. mysqli_query() combina la ejecución de sentencias y el almacenamiento en búfer de conjuntos de resultados.

Las aplicaciones PHP pueden navegar libremente a través de los resultados almacenados en búfer. La navegación es rápida porque los conjuntos de resultados se mantienen en la memoria del cliente. Por favor, tenga en cuenta que a menudo es más fácil escalar por cliente que escalar el servidor.

Y en http://php.net/manual/en/mysqli-result.fetch-all.php dice:

Como mysqli_fetch_all() devuelve todas las filas como una matriz en un solo paso, puede consumir más memoria que algunas funciones similares, como mysqli_fetch_array(), que solo devuelve una fila a la vez del conjunto de resultados. Además, si necesita iterar sobre el conjunto de resultados, necesitará una construcción de bucle que afectará aún más el rendimiento. Por estas razones, mysqli_fetch_all() solo debe usarse en aquellas situaciones en las que el conjunto de resultados obtenido se enviará a otra capa para su procesamiento.

Esto parece algo contradictorio. ¿Cuál es la diferencia entre el “búfer del conjunto de resultados del lado del cliente” y el “consumo de conjuntos de resultados”? Uno dice que se mantienen en la memoria del cliente y el otro dice leer fila por fila. Si todo está almacenado en el búfer de PHP, ¿por qué la última cita dice que si devuelve todas las filas como una matriz en un solo paso, puede consumir más memoria?

  • el almacenamiento en búfer se maneja internamente en el servidor sql, no en php

    – Dave

    26 de junio de 2013 a las 15:32

  • ¿Eso se relaciona con mi edición anterior? Si pudieras explicarme en tu respuesta, lo aceptaré. Gracias.

    – texalar

    26 de junio de 2013 a las 18:37

  • No debería llamarse almacenamiento en búfer tbh, debería llamarse caché de resultados. php contendrá un pequeño subconjunto del objeto de resultado completo y luego tendrá que extraer el resto de mysql. No puedo pensar en ninguna instancia de personas que hagan el lado del cliente en php a menos que eso signifique que php es el cliente de mysql. Mysql también realiza consultas internas de búfer y caché para hacer búsquedas más rápidas en lugar de tener que hacer lecturas de tablas completas, etc.

    – Dave

    26 de junio de 2013 a las 19:23

  • Aquí hay un buen recurso: hackingwithphp.com/9/4/9/…

    – Antonio

    20 de marzo de 2020 a las 12:31

avatar de usuario
dave

Ver: http://php.net/manual/en/mysqlinfo.concepts.buffering.php

Las consultas MySQL sin búfer ejecutan la consulta y luego devuelven un recurso mientras los datos aún están esperando en el servidor MySQL para ser recuperados. Esto usa menos memoria en el lado de PHP, pero puede aumentar la carga en el servidor. A menos que el conjunto de resultados completo se obtenga del servidor, no se pueden enviar más consultas a través de la misma conexión. Las consultas sin búfer también se pueden denominar “resultado de uso”.

Siguiendo estas características, las consultas almacenadas en búfer deben usarse en los casos en los que espera solo un conjunto de resultados limitado o necesita saber la cantidad de filas devueltas antes de leer todas las filas. El modo sin búfer debe usarse cuando espera resultados más grandes.

Las consultas almacenadas en búfer son predeterminadas.

Ejemplo sin búfer:

<?php
$mysqli  = new mysqli("localhost", "my_user", "my_password", "world");
$uresult = $mysqli->query("SELECT Name FROM City", MYSQLI_USE_RESULT);

if ($uresult) {
   while ($row = $uresult->fetch_assoc()) {
       echo $row['Name'] . PHP_EOL;
   }
}
$uresult->close();
?>

  • Buenos puntos. En realidad, puede usar varias declaraciones/consultas preparadas en la misma conexión usando free_result() para dejar de lado el recurso de resultado. Sin embargo, esto evitará que obtenga tuplas/filas adicionales de este conjunto de resultados.

    – Lars GyrupBrink Nielsen

    9 oct 2013 a las 10:15

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad