Php 太慢了

Php 太慢了,php,mysql,arrays,foreach,Php,Mysql,Arrays,Foreach,我有两个阵列: $questions: pid => name $answers: pid => rid 它在数据库中插入所有问题(pid),如果有答案(rid),则插入答案;如果没有答案,则插入0 foreach($questions as $value) { $idanswer = ($answers[$value[pid]]) ? $answers[$value[pid]] : 0; $idquestion = $value[pid]; $sql =

我有两个阵列:

$questions: pid => name
$answers: pid => rid
它在数据库中插入所有问题(pid),如果有答案(rid),则插入答案;如果没有答案,则插入0

foreach($questions as $value) {
    $idanswer = ($answers[$value[pid]]) ? $answers[$value[pid]] : 0;
    $idquestion = $value[pid];
    $sql = "INSERT INTO solucion ( rid, pid) VALUES ( '$idanswer ', '$idquestion ')";
    $db - > query($sql);
}

在我缺乏经验的情况下,我几乎所有的事情都使用foreach,但在这种情况下速度太慢了。有什么建议吗?

不要在PHP循环中包装单个
INSERT
查询,而是使用PHP循环在字符串中构建单个
INSERT
查询,然后在最后执行该单个查询

提示:可以同时插入多行


虽然单个
INSERT
很快,但是MySQL查询的组合往返总是会伸缩性很差,因为您正在为每个
N
数组元素重复连接/通信/解释/文件访问开销。。。所有这些都是不必要的。

我建议构建一个插入多个值的INSERT语句,因为每个记录的结构都是相同的

$values=[];
foreach($value形式的问题){
$idanswer=($answers[$value[pid]])?$answers[$value[pid]]:0;
$idquestion=$value[pid];
数组_push($values,“$idanswer”,“$idquestion”)”;
}
$db->query(“插入到解决方案(rid,pid)值中”。内爆(',',$VALUES));
上面的代码段将以以下形式构建INSERT语句

插入表(列、列)值('value','value'),('value','value'))
最好减少插入所有记录所需的数据库命中数


对于INSERT语句的完整引用,请阅读。

而不是针对要插入的每一行运行查询,为什么不在单个查询中插入所有行?问题是你在那里付出的昂贵成本,这肯定不是问题的根源

你为什么不按照以下的思路去做呢:

$sql = "INSERT INTO solucion (rid, pid) VALUES ";
$vls = array();
foreach($questions as $value) {
    $idanswer = ($answers[$value[pid]]) ? $answers[$value[pid]] : 0;
    $idquestion = $value[pid];
    $vls[] = " ( '$idanswer ', '$idquestion ')";

}
$sql .= implode(', ', $vls);
$db->query($sql);

这很慢,因为每个foreach迭代执行1个事务

在foreach循环中构建整个SQL语句,然后在foreach完成后执行一次

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

不要运行多条insert语句,而是构建一条insert语句,然后只运行一条语句。例如,见下文

$query = "INSERT INTO solucion ( rid, pid) VALUES";

foreach($questions as $value) {
    $idanswer = ($answers[$value[pid]]) ? $answers[$value[pid]] : 0;
    $idquestion = $value[pid];
    $query .= " ( '$idanswer ', '$idquestion '),";
}

$query = rtrim($query, ",").";";

$db - > query($sql);

我非常怀疑这与
foreach
有关,而是与您的数据库查询有关。
以我的经验,我几乎所有事情都使用foreach
,听到这个消息我很难过。您应该为所有新行生成一个
INSERT
查询。@Svish:
INSERT
将很快;其中1500人将不会被解雇。将单个
INSERT
包装到
foreach
中是错误的。@LightnessRacesinOrbit我可以向您保证,如果删除
$db->query($sql),循环将接近瞬时。它运行查询需要时间,这意味着解决方案,就像其他人在这里已经回答的一样,是最小化您运行的查询数量。与“foreach的速度”无关。@Svish:同意。但是当OP选择使用
foreach
来解决导致延迟的问题时,试图声称这与
foreach
无关似乎是一件奇怪的事情。不管怎样,结果证明我们都在用相反的方式说同样的话@我们都需要一些例子。在那个时代,例子应该补充以散文为基础的解释。你只是给了他一段代码,没有进一步的。。。这真是太可惜了。这也是SO被“为我制作代码”的非问题淹没的原因。OP需要的是一个指向正确方向的指针——OP只会复制和粘贴你的代码,而不知道为什么或是什么does@Jueecy这是你的责任。这是我们所有人的责任。否则你到底为什么在这里?这个答案现在好多了。我看不出区别。为什么要在这里添加另一个答案的副本。。。向上投票当前答案…我在任何答案出现之前单击了答案,在单击提交其他答案时,我的回答速度不如某些人快,抱歉。为什么要在此处添加另一个已存在答案的副本。。。更新当前答案…我更新了文本答案,它很好地描述了问题及其解决方案。感谢您指出。您也可以使用事务处理。只需在循环之前开始,然后提交即可。它将提高性能。仅适用于InnoDb表引擎。非常适用。在800k刀片上测试。同样,只有使用InnoDb@Vadim但你仍然在做不必要的80万次往返。也就是说,您不会对800k行使用单个字符串/查询。您是对的。我建议将此选项作为解决此问题的替代方法。这主要取决于主题,如果您需要获取最后一个插入的ID,并在另一个插入中使用它,并执行一些操作,则不能使用批插入。