我有大量的MySQL查询(1.8M行,25列),我需要从其中创建二维数组(基于主键的内存表)。
代码按预期工作,但$ table创建在PHP7.0中需要很长时间。
PHP7.0执行得如此糟糕的原因是什么?我的主要兴趣是在mysqli。
感谢您的任何见解 – 如果我可以修复性能,PHP7会节省大量内存。
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";
mysqli的结果
Deb 7 PHP 5.4 mysqlnd 5.0.10
1.8秒设置数组值
8.37秒执行查询
13.49秒获取数据
24.42秒执行整个脚本
高峰内存使用率:8426.75 MB
Deb 8 PHP 5.6 mysqlnd 5.0.11-dev
1.7秒设置数组值
8.58秒执行查询
12.55秒获取数据
23.6秒执行整个脚本
高峰内存使用率:8426.75 MB
Deb 8 PHP 7.0 mysqlnd 5.0.12-dev
0.73秒设置数组值
8.63秒执行查询
126.71秒获取数据
136.46秒执行整个脚本
峰值内存使用量:7394.27 MB
Deb 8 PHP 7.0 mysqlnd 5.0.12-dev扩展基准测试
我已经扩展了部分抓取的基准测试,每10万行报告一次,结果如下:
线在1.87s中提取了10万
线在5.24秒内提取了30万
线在10.97s中获得了500000
线在19.17s获得了70万
线在29.96s中获得了900000
线在43.03s中获得了1100000
线在58.48s中获得了1300000
线在76.47秒内获得了1500000
线在96.73s中获得了1700000
线在107.78s中获得了1800000
DEB8 PHP7.1.0-dev libclient 5.5.50
1.56秒设置数组值
8.38秒执行查询
456.52秒获取数据
467.68秒执行整个脚本
峰值内存使用率:8916 MB
DEB8 PHP7.1.0-dev libclient 5.5.50扩展基准测试
线在2.72秒内获取了10万
线在15.7s中获取了30万
线在38.7s中获得了500000
线在71.69s获得了70万
线在114.8s中获得了900000
线在168.18s中获得了1100000
线在231.69s中获得了1300000
线在305.36s中获取了1500000
线在389.05s取得了1700000
线在434.71s中获得了1800000
DEB8 PHP7.1.0-dev mysqlnd 5.0.12-dev
1.51秒设置数组值
9.16秒执行查询
261.72秒获取数据
273.61秒执行整个脚本
峰值内存使用量:8984.27 MB
DEB8 PHP7.1.0-dev mysqlnd 5.0.12-dev扩展基准测试
线在3.3s中获取了100000
线在13.63秒内获得了30万
线在29.02秒获得了500000
线在49.21秒获得了70万
线在74.56s中获得了900000
线在104.97s取得了1100000
线在140.03s中获得了1300000
线在180.42秒内获得了1500000
线在225.72秒内获得1700000
线在250.01秒内获得了1800000
PDO代码段
$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";
PDO结果
Deb 7 PHP 5.4 mysqlnd 5.0.10
1.85秒设置数组值
12.51秒执行查询
16.75秒获取数据
31.82秒执行整个脚本
峰值内存使用量:11417.5 MB
Deb 8 PHP 5.6 mysqlnd 5.0.11-dev
1.75秒设置数组值
12.16秒执行查询
15.72秒获取数据
30.39秒执行整个脚本
峰值内存使用量:11417.75 MB
Deb 8 PHP 7.0 mysqlnd 5.0.12-dev
0.71秒设置数组值
35.93秒执行查询
114.16秒获取数据
151.19秒执行整个脚本
峰值内存使用量:6620.29 MB
基线比较代码
$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';
所有系统的执行时间类似于19秒-1秒变化。
基于上述观察,我会说PHP 5.X是合理的,因为执行的工作要比转储到文件要多一些。
>所有3台服务器位于同一主机(源和两台测试服务器)
>重复时测试一致
>内存中已经有类似的变量,我需要做比较删除进行测试,与问题无关
CPU整个时间是100%
>两台服务器的32G RAM和swappiness设置为1,目标是执行它作为内存操作
>测试服务器是专用的,没有其他的运行
> php.ini在主版本之间改变,但与mysqli / PDO有关的所有选项似乎都是一样的
> Deb8机器降级到PHP5.6并且问题消失了,在重新安装PHP7之后
>报告了一个错误在php.net – ID 72736,因为我相信已经证明问题是在PHP,而不是在系统或任何其他配置
编辑1:添加了PDO比较
编辑2:添加基准测试标记,编辑PDO结果,因为有基准测试错误
编辑3:在原始问题中进行主要清理,重建代码狙击手以更好地指示错误
编辑4:关于降级升级的补充说明
编辑5:为DEB8 PHP7.0添加扩展基准测试
编辑6:包含php7配置
编辑7:性能测量为PHP 7.1开发与两个库 – 编译与配置从主教,删除我的php配置
编辑8:添加与CLI命令的比较,次要清理