Php 这段代码需要循环350万行,我如何才能使它更高效?
我有一个csv文件,其中包含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看起来像
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行。您还可以在发生这种情况时向用户显示状态。唯一的问题是,如果页面不知何故没有刷新,那么导入就会停止
在使用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,…)你介意告诉我我需要写什么吗?csv的格式是代码,(换行)代码,(换行)代码,(换行)代码,(换行),但我需要以(“”,code,0)的格式插入。将csv处理成有用的内容并导入该内容不是更快吗。@Hailwood在第一列和第三列分别应用默认值'
和0
(在表定义中)并仅将第二列插入表foo(第二列名称)
。
INSERT INTO tbl_name (a,b,c) VALUES(1,2,3),(4,5,6),(7,8,9);