PHP 文件写入 (fwrite / file_put_contents) speed/optimization
PHP File Writing (fwrite / file_put_contents) speed/optimization
所以,我有一个包含大数据的数据库。当前要使用的数据约为 2.6 GB。
所有数据都需要写入一个文本文件,以便以后在其他脚本中使用。
每个文件的数据是有限的,并分成多个部分。每个文件 100 个结果(每个文件约 37MB)。那是大约 71 个文件。
数据是json序列化然后用openssl加密的数据。
数据正在正确写入文件,直到 240 秒后达到最大执行时间。那是在大约 20 个文件之后...
好吧,我可以延长那个时间,但这不是问题。
问题如下:
Writing file 1-6: +/- 5 seconds
Writing file 7-8: +/- 7 seconds
Writing file 9-11: +/- 12 seconds
Writing file 12-14: +/- 17 seconds
Writing file 14-16: +/- 20 seconds
Writing file 16-18: +/- 23 seconds
Writing file 19-20: +/- 27 seconds
Note: time is needed time per file
换句话说,每写入一个文件,每个文件的写入时间都会显着增加,这就是导致脚本运行缓慢的原因。
脚本的结构有点像这样:
$needed_files = count needed files/parts
for ($part=1; $part<=$needed_files; $part++) { // Loop throught parts
$query > mysqli select data
$data > json_encode > serialize > openssl_encrypyt
file_put_contents($filename.$part, $data, LOCK_EX);
}
帮助后的工作代码
$notchDetails = mysqli_query($conn, "SELECT * FROM notches WHERE projectid = ".$projectid."");
$rec_count = 0;
$limit = 100;
$part = 1;
while ($notch = mysqli_fetch_assoc($notchDetails)) {
$data1[] = $notch;
$rec_count++;
if ($rec_count >= $limit) {
$data = json_encode($data1);
$data = openssl_encrypt(bin2hex($data), "aes128", $pass, false, $iv);
$filename = $mainfolder."/".$projectfolder."/".$subfolder."/".$fname.".part".$part."".$fext;
file_put_contents($filename, $data, LOCK_EX);
$part++;
$rec_count = 0;
$data = $data1 = "";
}
}
if ($data1 != "") {
$data = json_encode($data1);
$data = openssl_encrypt(bin2hex($data), "aes128", $pass, false, $iv);
$filename = $mainfolder."/".$projectfolder."/".$subfolder."/".$fname.".part".$part."".$fext;
file_put_contents($filename, $data, LOCK_EX);
}
mysqli_free_result($notchDetails);
就我个人而言,我会将其编码为单个 SELECT,没有 LIMIT,然后基于 $rec_per_file = ?;
从单个 while get results
循环
中写入输出
请原谅我的神秘代码,您没有给我们提供太多线索
<?php
//ini_set('max_execution_time', 600); // only use if you have to
$filename = 'something';
$filename_suffix = 1;
$rec_per_file = 100;
$sql = "SELECT ....";
Run query
$rec_count = 0;
while ( $row = fetch a row ) {
$data[] = serialize > openssl_encrypyt
$rec_count++;
if ( $rec_count >= $rec_per_file ) {
$json_string = json_encode($data);
file_put_contents($filename.$filename_suffix,
$json_string,
LOCK_EX);
$filename_suffix++; // inc the suffix
$rec_count = 0; // reset counter
$data = array(); // clear data
// add 30 seconds to the remaining max_execution_time
// or at least a number >= to the time you expect this
// while loop to get back to this if statement
set_time_limit(30);
}
}
// catch the last few rows
$json_string = json_encode($data);
file_put_contents($filename.$filename_suffix, $data, LOCK_EX);
我也不确定你为什么要 serialize()
和 json_encode()
根据您对执行时间的评论,我有了一个想法。如果在 while
循环内的 if
内放置一个 set_time_limit(seconds)
它可能会更干净,并且您不必将 ini_set('max_execution_time', 600);
设置为一个非常大的数字,如果您这里有一个真正的错误可能会导致 PHP 在踢出脚本之前继续处理很长时间。
来自手册:
Set the number of seconds a script is allowed to run. If this is reached, the script returns a fatal error. The default limit is 30 seconds or, if it exists, the max_execution_time value defined in the php.ini.
When called, set_time_limit() restarts the timeout counter from zero. In other words, if the timeout is the default 30 seconds, and 25 seconds into script execution a call such as set_time_limit(20) is made, the script will run for a total of 45 seconds before timing out.
所以,我有一个包含大数据的数据库。当前要使用的数据约为 2.6 GB。
所有数据都需要写入一个文本文件,以便以后在其他脚本中使用。
每个文件的数据是有限的,并分成多个部分。每个文件 100 个结果(每个文件约 37MB)。那是大约 71 个文件。
数据是json序列化然后用openssl加密的数据。
数据正在正确写入文件,直到 240 秒后达到最大执行时间。那是在大约 20 个文件之后...
好吧,我可以延长那个时间,但这不是问题。
问题如下:
Writing file 1-6: +/- 5 seconds
Writing file 7-8: +/- 7 seconds
Writing file 9-11: +/- 12 seconds
Writing file 12-14: +/- 17 seconds
Writing file 14-16: +/- 20 seconds
Writing file 16-18: +/- 23 seconds
Writing file 19-20: +/- 27 seconds
Note: time is needed time per file
换句话说,每写入一个文件,每个文件的写入时间都会显着增加,这就是导致脚本运行缓慢的原因。
脚本的结构有点像这样:
$needed_files = count needed files/parts
for ($part=1; $part<=$needed_files; $part++) { // Loop throught parts
$query > mysqli select data
$data > json_encode > serialize > openssl_encrypyt
file_put_contents($filename.$part, $data, LOCK_EX);
}
帮助后的工作代码
$notchDetails = mysqli_query($conn, "SELECT * FROM notches WHERE projectid = ".$projectid."");
$rec_count = 0;
$limit = 100;
$part = 1;
while ($notch = mysqli_fetch_assoc($notchDetails)) {
$data1[] = $notch;
$rec_count++;
if ($rec_count >= $limit) {
$data = json_encode($data1);
$data = openssl_encrypt(bin2hex($data), "aes128", $pass, false, $iv);
$filename = $mainfolder."/".$projectfolder."/".$subfolder."/".$fname.".part".$part."".$fext;
file_put_contents($filename, $data, LOCK_EX);
$part++;
$rec_count = 0;
$data = $data1 = "";
}
}
if ($data1 != "") {
$data = json_encode($data1);
$data = openssl_encrypt(bin2hex($data), "aes128", $pass, false, $iv);
$filename = $mainfolder."/".$projectfolder."/".$subfolder."/".$fname.".part".$part."".$fext;
file_put_contents($filename, $data, LOCK_EX);
}
mysqli_free_result($notchDetails);
就我个人而言,我会将其编码为单个 SELECT,没有 LIMIT,然后基于 $rec_per_file = ?;
从单个 while get results
循环
请原谅我的神秘代码,您没有给我们提供太多线索
<?php
//ini_set('max_execution_time', 600); // only use if you have to
$filename = 'something';
$filename_suffix = 1;
$rec_per_file = 100;
$sql = "SELECT ....";
Run query
$rec_count = 0;
while ( $row = fetch a row ) {
$data[] = serialize > openssl_encrypyt
$rec_count++;
if ( $rec_count >= $rec_per_file ) {
$json_string = json_encode($data);
file_put_contents($filename.$filename_suffix,
$json_string,
LOCK_EX);
$filename_suffix++; // inc the suffix
$rec_count = 0; // reset counter
$data = array(); // clear data
// add 30 seconds to the remaining max_execution_time
// or at least a number >= to the time you expect this
// while loop to get back to this if statement
set_time_limit(30);
}
}
// catch the last few rows
$json_string = json_encode($data);
file_put_contents($filename.$filename_suffix, $data, LOCK_EX);
我也不确定你为什么要 serialize()
和 json_encode()
根据您对执行时间的评论,我有了一个想法。如果在 while
循环内的 if
内放置一个 set_time_limit(seconds)
它可能会更干净,并且您不必将 ini_set('max_execution_time', 600);
设置为一个非常大的数字,如果您这里有一个真正的错误可能会导致 PHP 在踢出脚本之前继续处理很长时间。
来自手册:
Set the number of seconds a script is allowed to run. If this is reached, the script returns a fatal error. The default limit is 30 seconds or, if it exists, the max_execution_time value defined in the php.ini.
When called, set_time_limit() restarts the timeout counter from zero. In other words, if the timeout is the default 30 seconds, and 25 seconds into script execution a call such as set_time_limit(20) is made, the script will run for a total of 45 seconds before timing out.