Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/64.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 这段代码需要循环350万行,我如何才能使它更高效?_Php_Mysql_Optimization - Fatal编程技术网

Php 这段代码需要循环350万行,我如何才能使它更高效?

Php 这段代码需要循环350万行,我如何才能使它更高效?,php,mysql,optimization,Php,Mysql,Optimization,我有一个csv文件,其中包含350万个代码。 我应该指出,这只会是这一次 csv看起来像 age9tlg, rigfh34, ... 这是我的密码: ini_set('max_execution_time', 600); ini_set("memory_limit", "512M"); $file_handle = fopen("Weekly.csv", "r"); while (!feof($file_handle)) { $line_of_text = fgetcsv($f

我有一个csv文件,其中包含350万个代码。
我应该指出,这只会是这一次

csv看起来像

age9tlg,  
rigfh34,  
...
这是我的密码:

ini_set('max_execution_time', 600);
ini_set("memory_limit", "512M");
$file_handle = fopen("Weekly.csv", "r");
while (!feof($file_handle)) {
    $line_of_text = fgetcsv($file_handle);

    if (is_array($line_of_text))
        foreach ($line_of_text as $col) {
            if (!empty($col)) {
                mysql_query("insert into `action_6_weekly` Values('$col', '')") or die(mysql_error());
            }
    } else {
        if (!empty($line_of_text)) {
            mysql_query("insert into `action_6_weekly` Values('$line_of_text', '')") or die(mysql_error());
        }
    }
}
fclose($file_handle);
这个密码会在我身上半途而废吗? 我的内存和最大执行时间是否足够高

注意: 此代码将在我的本地主机上运行,并且数据库位于同一台PC上,因此延迟不是问题


更新:
这里是另一个可能的实现。 这一次是在2000条记录的批量插入中完成的

$file_handle = fopen("Weekly.csv", "r");
$i = 0;
$vals = array();
while (!feof($file_handle)) {
    $line_of_text = fgetcsv($file_handle);

    if (is_array($line_of_text))
        foreach ($line_of_text as $col) {
            if (!empty($col)) {
                if ($i < 2000) {
                    $vals[] = "('$col', '')";
                    $i++;
                } else {
                    $vals = implode(', ', $vals);
                    mysql_query("insert into `action_6_weekly` Values $vals") or die(mysql_error());
                    $vals = array();
                    $i = 0;
                }
            }
        } else {
        if (!empty($line_of_text)) {
            if ($i < 2000) {
                $vals[] = "('$line_of_text', '')";
                $i++;
            } else {
                $vals = implode(', ', $vals);
                mysql_query("insert into `action_6_weekly` Values $vals") or die(mysql_error());
                $vals = array();
                $i = 0;
            }
        }
    }
}
fclose($file_handle);
但现在的问题是,我对csv格式的看法是错误的, 实际上是4个代码然后换行, 所以 fhroflg、qporlfg、vcalpfx、rplfigc,
vapworf、flofigx、apqoeei、clxosrc,
...

因此,我需要能够指定以
这个问题已扩展到其他领域


更新3
将其设置为使用

while (!feof($file_handle)) {
   $val[] = fgetcsv($file_handle);
   $i++;
   if($i == 20000) {
      //do insert
      //set $i = 0;
      //$val = array();
   }
}

//do insert(for last few rows that dont reach 20k
但由于某种原因,$val包含7.5万行,它在这一点上消失了,你知道为什么吗?
注:上述代码已简化

这个代码会半途而废吗 对我了结了吗?我的记忆和max 执行时间足够长吗

你为什么不试试看呢

您可以调整内存(
memory\u limit
)和执行时间(
max\u execution\u time
)限制,因此如果您真的必须使用这些限制,这应该不是问题

请注意,MySQL支持延迟和多行插入:

INSERT INTO tbl_name (a,b,c) VALUES(1,2,3),(4,5,6),(7,8,9);

我怀疑这是否是流行的答案,但我会让您的php应用程序在csv文件上运行。当然,它的优化远远超出了您在php中所做的工作。

您应该累积这些值,并在最后一次将它们全部插入数据库,或者每x个记录一次批量插入。对每行执行一个查询意味着350万个SQL查询,每个查询都会带来相当大的开销

另外,您应该在命令行上运行它,这样就不需要担心执行时间限制


然而,真正的答案是邪恶小丑的答案,从CSV导入MySQL已经是一个解决了的问题。

我希望没有web客户端在等待对此的响应。除了调用已经引用的导入实用程序之外,我会将其作为作业启动,并几乎立即将反馈返回给客户机。让插入循环在某个地方更新完成百分比,以便最终用户可以检查状态,如果您绝对必须这样做。

2种可能的方法

1) 批处理该进程,然后在更新状态的同时让计划作业导入该文件。通过这种方式,您可以拥有一个页面,该页面不断检查状态,如果状态尚未达到100%,则刷新页面本身。用户将实时更新所做的工作。但为此,您需要访问操作系统才能设置调度任务。当没有要导入的内容时,任务将空闲运行

2) 让页面处理1000行(或任意N行数…由您决定),然后向浏览器发送一个java脚本,用一个新参数刷新自身,以告诉脚本处理接下来的1000行。您还可以在发生这种情况时向用户显示状态。唯一的问题是,如果页面不知何故没有刷新,那么导入就会停止

  • 确保表上没有索引,因为索引会减慢插入速度(在完成所有插入后添加索引)
  • 不要在循环的每次调用中创建新的SQL语句,而是尝试在循环外执行语句,并在循环内使用参数执行准备好的语句。根据数据库的不同,这可以加快堆的速度

  • 在使用perl将大型Access数据库导入Postgres时,我已经完成了上述操作,并将插入时间缩短到30秒。我本来会使用导入器工具,但我希望perl在插入时强制执行一些规则。

    很明显,按顺序插入350万条记录效率极低。SQL Server对于大批量插入具有特殊的批量复制语义;你应该在MySQL中寻找类似的东西。如果你不需要一次运行所有这些东西,你可以按部分运行它,比如每X分钟运行X个条目。所以,我试着在200k行上进行批量插入,是的,这是一个有趣的错误;MySQL服务器已经离开了洛威尔。。。我认为,在这种情况下,使用
    for
    与使用
    foreach
    是值得的@亚历克斯:哈哈,你在跟踪我吗是的,你是对的,但问题不在于循环,而在于在这个过程中不杀掉mysql,哈哈,经典的“我会为此被否决”。该策略适用于我:+1。是否可以设置以结尾的两行?考虑到这会直接映射到文件中的加载数据csv的格式不正确,它缺少一些列。@Hailwood这应该不是问题,请参阅手册中的示例:
    Load Data infle'persondata.txt'到表persondata(col1,col2,…)'
    0
    (在表定义中)并仅将第二列插入表foo(第二列名称)
    INSERT INTO tbl_name (a,b,c) VALUES(1,2,3),(4,5,6),(7,8,9);