query - php mysqli select all from table
mysqli_fetch_assoc() rendimiento PHP5.4 vs PHP7.0 (2)
Tengo una gran consulta de MySQL (1.8M filas, 25 columnas) y necesito hacer una matriz bidimensional a partir de ella (tabla de memoria basada en clave principal).
El código funciona como se esperaba, pero la creación de $ table lleva mucho tiempo en PHP7.0.
¿Cuál es la razón por la que PHP7.0 funciona mucho peor? Mi principal interés está en mysqli .
Gracias por cualquier información: PHP7 me ahorraría mucha memoria si puedo arreglar el rendimiento.
código de mysqli
$start = microtime(true);
$vysledek = cluster::query("SELECT * FROM `table` WHERE 1");
$query_time = (microtime(true) - $start);
$start_fetch = microtime(true);
while($zaznam = mysqli_fetch_assoc ( $vysledek )){
$fetch_time+= (microtime(true) - $start_fetch);
$start_assign = microtime(true);
$table[$zaznam[''prikey'']] = $zaznam;
$assign_time+= (microtime(true) - $start_assign);
$start_fetch = microtime(true);
}
$total_time+= (microtime(true) - $start);
echo round($assign_time, 2).'' seconds to set the array values/n'';
echo round($query_time, 2).'' seconds to execute the query/n'';
echo round($fetch_time, 2).'' seconds to fetch data/n'';
echo round($total_time, 2).'' seconds to execute whole script/n'';
echo "Peak Memory Usage:".round(memory_get_peak_usage(true)/(1024 * 1024), 2)." MB/n";
resultados de mysqli
Deb 7 PHP 5.4 mysqlnd 5.0.10
1.8 segundos para establecer los valores de la matriz
8.37 segundos para ejecutar la consulta.
13.49 segundos para recuperar datos
24.42 segundos para ejecutar el script completo.
Uso máximo de la memoria: 8426.75 MB
Deb 8 PHP 5.6 mysqlnd 5.0.11-dev
1.7 segundos para establecer los valores de la matriz
8.58 segundos para ejecutar la consulta.
12.55 segundos para recuperar datos
23.6 segundos para ejecutar el script completo.
Uso máximo de la memoria: 8426.75 MB
Deb 8 PHP 7.0 mysqlnd 5.0.12-dev
0.73 segundos para establecer los valores de la matriz
8.63 segundos para ejecutar la consulta.
126.71 segundos para recuperar datos
136.46 segundos para ejecutar el script completo.
Uso máximo de la memoria: 7394.27 MB
Deb 8 PHP 7.0 mysqlnd 5.0.12-dev benchmarking extendido
He ampliado la evaluación comparativa para la obtención de secciones para informar cada 100 mil líneas con los siguientes resultados:
Líneas alcanzadas 100000 en 1.87s
Líneas recogidas 300000 en 5.24s
Líneas alcanzadas 500000 en 10.97s
Líneas alcanzadas 700000 en 19.17s
Líneas captadas 900000 en 29.96s
Líneas alcanzadas 1100000 en 43.03s
Líneas recogidas 1300000 en 58.48s
Líneas captadas 1500000 en 76.47s
Líneas captadas 1700000 en 96.73s
Líneas recogidas 1800000 en 107.78s
DEB8 PHP7.1.0-dev libclient 5.5.50
1.56 segundos para establecer los valores de la matriz
8.38 segundos para ejecutar la consulta.
456.52 segundos para recuperar datos
467.68 segundos para ejecutar el script completo.
Uso máximo de la memoria: 8916 MB
DEB8 PHP7.1.0-dev libclient 5.5.50 benchmarking extendido
Líneas alcanzadas 100000 en 2.72s
Líneas recogidas 300000 en 15.7s
Líneas alcanzadas 500000 en 38.7s
Líneas alcanzadas 700000 en 71.69s
Líneas captadas 900000 en 114.8s
Líneas alcanzadas 1100000 en 168.18s
Líneas alcanzadas 1300000 en 231.69s
Líneas captadas 1500000 en 305.36s
Líneas captadas 1700000 en 389.05s
Líneas alcanzadas 1800000 en 434.71s
DEB8 PHP7.1.0-dev mysqlnd 5.0.12-dev
1.51 segundos para establecer los valores de la matriz
9.16 segundos para ejecutar la consulta.
261.72 segundos para recuperar datos
273.61 segundos para ejecutar el script completo.
Uso máximo de la memoria: 8984.27 MB
DEB8 PHP7.1.0-dev mysqlnd 5.0.12-dev benchmarking extendido
Líneas alcanzadas 100000 en 3.3s
Líneas recogidas 300000 en 13.63 s
Líneas alcanzadas 500000 en 29.02s
Líneas alcanzadas 700000 en 49.21s
Líneas captadas 900000 en 74.56s
Líneas alcanzadas 1100000 en 104.97s
Líneas captadas 1300000 en 140.03s
Líneas captadas 1500000 en 180.42s
Líneas captadas 1700000 en 225.72s
Líneas recogidas 1800000 en 250.01s
Fragmento de código de DOP
$start = microtime(true);
$sql = "SELECT * FROM `table` WHERE 1";
$vysledek = $dbh->query($sql, PDO::FETCH_ASSOC);
$query_time = (microtime(true) - $start);
$start_fetch = microtime(true);
foreach($vysledek as $zaznam){
$fetch_time+= (microtime(true) - $start_fetch);
$start_assign = microtime(true);
$table[$zaznam[''prikey'']] = $zaznam;
$assign_time+= (microtime(true) - $start_assign);
$start_fetch = microtime(true);
}
$total_time+= (microtime(true) - $start);
echo round($assign_time, 2).'' seconds to set the array values/n'';
echo round($query_time, 2).'' seconds to execute the query/n'';
echo round($fetch_time, 2).'' seconds to fetch data/n'';
echo round($total_time, 2).'' seconds to execute whole script/n'';
echo "Peak Memory Usage:".round(memory_get_peak_usage(true)/(1024 * 1024), 2)." MB/n";
Resultados de la DOP
Deb 7 PHP 5.4 mysqlnd 5.0.10
1.85 segundos para establecer los valores de la matriz
12.51 segundos para ejecutar la consulta.
16.75 segundos para recuperar datos
31.82 segundos para ejecutar el script completo.
Uso máximo de la memoria: 11417.5 MB
Deb 8 PHP 5.6 mysqlnd 5.0.11-dev
1.75 segundos para establecer los valores de la matriz
12.16 segundos para ejecutar la consulta.
15.72 segundos para recuperar los datos
30.39 segundos para ejecutar el script completo.
Uso máximo de la memoria: 11417.75 MB
Deb 8 PHP 7.0 mysqlnd 5.0.12-dev
0.71 segundos para establecer los valores de la matriz
35.93 segundos para ejecutar la consulta.
114.16 segundos para recuperar datos
151.19 segundos para ejecutar el script completo.
Uso máximo de la memoria: 6620.29 MB
Código de comparación de línea de base
$start_query = microtime(true);
exec("mysql --user=foo --host=1.2.3.4 --password=bar -e''SELECT * FROM `profile`.`table`'' > /tmp/out.csv");
$query_time = (microtime(true) - $start_query);
echo round($query_time, 2).'' seconds to execute the query /n'';
El tiempo de ejecución es similar para todos los sistemas con una variación de 19 segundos + -1 segundo.
Según las observaciones anteriores, diría que PHP 5.X es razonable, ya que hay un poco más de trabajo ejecutado que solo volcar el archivo.
- los 3 servidores están en el mismo host (origen y ambos servidores de prueba)
- las pruebas son consistentes cuando se repiten
-
ya hay una variable similar en la memoria, necesito hacerlo para la comparacióneliminada para la prueba, no está relacionado con el problema - CPU está al 100% todo el tiempo
- Ambos servidores tienen 32G de RAM y el nivel de velocidad establecido en 1, el objetivo es realizarlo como operación de memoria
- El servidor de prueba está dedicado, no hay nada más en ejecución.
- php.ini cambió entre las versiones principales, pero todas las opciones relacionadas con mysqli / PDO parecen ser las mismas
La máquina Deb8 se actualizó a PHP5.6 y el problema desapareció, luego de reinstalar PHP7 en su parte posterior
Se informó un error en php.net - ID 72736 ya que creo que se demostró que el problema está en PHP y no en el sistema ni en ninguna otra configuración
Edición 1 : Comparación de DOP agregada
Edición 2 : Se agregaron marcadores de puntos de referencia, se editaron los resultados de PDO ya que hubo un error de puntos de referencia
Edición 3 : limpieza importante en la pregunta original, reconstrucción de fragmentos de código para una mejor indicación del error
Edición 4 : punto añadido sobre la degradación y actualización de PHP
Edición 5 : agregado de benchmarking extendido para DEB8 PHP7.0
Edición 6 : configuración php7 incluida
Edición 7 : medición de rendimiento para PHP 7.1 dev con ambas bibliotecas, compiladas con configuraciones de bishop, eliminé mi configuración de php
Edición 8 : comparación agregada con el comando CLI, limpiezas menores
Como el problema parece estar en la zona de búsqueda (no en la creación de la matriz), sabemos que el controlador ejecuta mysqlnd
(que es una biblioteca de controladores escrita independientemente por el equipo de PHP, no proporcionada por MySQL AB alias Oracle), y luego vuelve a compilar PHP usando libmysqlclient
(que es la interfaz provista por MySQL AB o Oracle) puede mejorar la situación (o al menos reducir el espacio del problema).
Lo primero que sugeriría es escribir un pequeño script que se pueda ejecutar desde la CLI que demuestre el problema. Esto ayudará a eliminar cualquier otra variable (módulos de servidor web, opcache, etc.).
Entonces, sugeriría reconstruir PHP con libmysqlclient
para ver si mejora el rendimiento. Guía rápida para la reconstrucción de PHP (para los técnicamente competentes):
- Descarga la fuente para la versión de PHP que deseas.
- Descomprimir y entrar en el directorio de código PHP
- Ejecutar
./buildconf
- Ejecute
./configure --prefix=/usr --with-config-file-path=/etc/php5/apache2 --with-config-file-scan-dir=/etc/php5/apache2/conf.d --build=x86_64-linux-gnu --host=x86_64-linux-gnu --sysconfdir=/etc --localstatedir=/var --mandir=/usr/share/man --enable-debug --disable-static --with-pic --with-layout=GNU --with-pear=/usr/share/php --with-libxml-dir=/usr --with-mysql-sock=/var/run/mysqld/mysqld.sock --enable-dtrace --without-mm --with-mysql=shared,/usr --with-mysqli=shared,/usr/bin/mysql_config --enable-pdo=shared --without-pdo-dblib --with-pdo-mysql=shared,/usr CFLAGS="-g -O2 -fstack-protector-strong -Wformat -Werror=format-security -O2 -Wall -fsigned-char -fno-strict-aliasing -g" LDFLAGS="-Wl,-z,relro" CPPFLAGS="-D_FORTIFY_SOURCE=2" CXXFLAGS="-g -O2 -fstack-protector-strong -Wformat -Werror=format-security"
- Ejecutar
make && make test
- Alejarse
- Ejecute
sapi/cli/php -i
y confirme la versión y presencia de libmysqlclient
Ejecute su prueba de nuevo. Algo mejor
Para referencias cruzadas: con el lanzamiento de PHP 7.1 el 1 de diciembre de 2016, este problema debe resolverse (en PHP 7.1).
PHP 7.0 : Incluso en el ticket está escrito que PHP-7.0 ha sido parchado, aún no he visto en el registro de cambios reciente ( 7.0.13 el 10 de noviembre de 2016 , desde la fecha de incorporación del parche) que esto es parte de la actual Liberación de PHP 7.0.x. Tal vez con el próximo lanzamiento.
El error se rastrea en sentido ascendente (gracias al informe de OP): Error n. ° 72736: rendimiento lento al obtener conjuntos de datos grandes con mysqli / PDO (bugs.php.net; agosto de 2016).