Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/250.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PHP循环-导致严重延迟的表达式/函数_Php_Performance_Loops - Fatal编程技术网

PHP循环-导致严重延迟的表达式/函数

PHP循环-导致严重延迟的表达式/函数,php,performance,loops,Php,Performance,Loops,我想知道是否有人能解释这个问题。。PHP 5.3.0:) 我有一个循环,它抓取CSV文件的内容(大,200mb),处理数据,为mysql插入构建一个变量堆栈,一旦循环完成并创建了变量,我就插入信息 首先,mysql insert执行得很好,没有延迟,一切都很好,但是循环本身有延迟,我最初使用fgetcsv()来读取CSV文件,但是与file_get_contents()相比,这有一个严重的延迟-所以我切换到file_get_contents()。循环将在几秒钟内执行,直到我尝试添加一个函数(我还

我想知道是否有人能解释这个问题。。PHP 5.3.0:)

我有一个循环,它抓取CSV文件的内容(大,200mb),处理数据,为mysql插入构建一个变量堆栈,一旦循环完成并创建了变量,我就插入信息

首先,mysql insert执行得很好,没有延迟,一切都很好,但是循环本身有延迟,我最初使用fgetcsv()来读取CSV文件,但是与file_get_contents()相比,这有一个严重的延迟-所以我切换到file_get_contents()。循环将在几秒钟内执行,直到我尝试添加一个函数(我还在循环中添加了表达式,但没有添加函数来查看它是否有帮助)来创建一个包含每行CSV数据的数组,这就是导致解析时间严重延迟的原因!(基于这个200mb的文件,差异大约为30秒,但我想这取决于csv文件的文件大小)

下面是一些代码,您可以看到我在做什么:

$filename = "file.csv";
$content = file_get_contents($filename);    
$rows = explode("\n", $content);    
foreach ($rows as $data) {    
    $data = preg_replace("/^\"(.*)\"$/","$1",preg_split("/,(?=(?:[^\"]*\"[^\"]*\")*(?![^\"]*\"))/", trim($data))); //THIS IS THE CULPRIT CAUSING SLOW LOADING?!?
}
运行上述循环时,将在没有线路的情况下几乎立即执行:

$data = preg_replace("/^\"(.*)\"$/","$1",preg_split("/,(?=(?:[^\"]*\"[^\"]*\")*(?![^\"]*\"))/", trim($data)));
我还尝试创建如下函数(在循环之外):

并调用函数而不是一行程序:

$data = csv_string_to_array($data);
又一次没有运气:(

如果您能在这方面提供任何帮助,我猜fgetcsv函数的执行方式与此非常相似,它会导致延迟,通过数据行循环并创建一个数组


Danny

我找到了一个部分解决方案,我一次只发送1000行循环的批处理(php循环1000行,直到到达文件末尾)

然后我只设置:

$data = preg_replace("/^\"(.*)\"$/","$1",preg_split("/,(?=(?:[^\"]*\"[^\"]*\")*(?![^\"]*\"))/", trim($data)));
在1000行上,这样就不会对导致问题的整个文件进行设置


现在,它正在1-2秒内循环并将1000行插入mysql数据库,我对此很满意。我已经设置了脚本以循环1000行,记住它的最后位置,然后循环到下一个1000行,直到结束,它似乎工作正常!

我认为主要原因是preg_split()regexp的复杂性。 explode()可能会占用几秒钟的时间

$content = file_get_contents($filename);    
$rows = explode("\n", $content); 
可替换为:

$rows = file ($filename); // returns an array

但是,我支持ITroubs的上述建议,fgetcsv()可能是一个更好的解决方案。

顺便说一句,我不认为您的函数正在做您认为应该做的事情:当您退出循环时,它实际上不会修改$rows数组。要做到这一点,您需要更类似于:

foreach ($rows as $key => $data) {
    $rows[$key]=preg_replace("/^\"(.*)\"$/","$1",preg_split("/,(?=(?:[^\"]*\"[^\"]*\")*(?![^\"]*\"))/", trim($data)));

正则表达式子表达式(以“(…”)为界)是问题所在。向表达式添加这些子表达式可以大大降低其性能,这一点很简单。我要尝试的第一件事是停止使用preg_replace()来简单地删除前导和尾随双引号(trim()更适合)看看这有多大帮助。之后,您可能需要尝试一种非正则表达式的方式来解析该行。

我建议使用fgetcsv解析数据。似乎内存可能是您最大的影响。因此,为了避免消耗200MB的RAM,您应该按如下方式逐行解析:

$fp = fopen($input, 'r');

while (($row = fgetcsv($fp, 0, ',', '"')) !== false) {
    $out = '"' . implode($row, '", "') . '"';  // quoted, comma-delimited output
    // perform work
}
或者:在preg中使用条件通常非常昂贵。使用
explode()
trim()
及其
$charlist
参数处理这些行有时会更快

另一种选择是,如果仍要使用preg,请添加S修饰符以尝试加快表达式的速度


S
当一个模式要被多次使用时,值得花更多的时间来分析它,以加快匹配所需的时间。如果设置了此修饰符,则会执行此额外的分析。目前,研究模式仅适用于没有固定起始字符的非锚定模式


您是否尝试过使用“for”循环而不是“foreach”?是否已经尝试过比较整个时间,直到您的方法与fgetcsv()的数据在数组中?preg_replace和preg_split是重量级函数,因为基于正则表达式处理字符串是一项cpu密集型任务。将函数调用放入另一个函数无法加快任何速度。我认为
fgetcsv
对于emmerman来说会比+1快。为什么不能使用fgetcsv(),danny,这是专门为读取/解析CSV数据而设计的?@Wallgate-A for循环实际上比foreach慢,因为它需要更多的脚本操作码来处理计数器和条件。
$fp = fopen($input, 'r');

while (($row = fgetcsv($fp, 0, ',', '"')) !== false) {
    $out = '"' . implode($row, '", "') . '"';  // quoted, comma-delimited output
    // perform work
}