【问题标题】:Queries in loop taking too much time to execute循环中的查询花费太多时间来执行
【发布时间】:2019-01-31 05:42:17
【问题描述】:

我正在尝试使用 Ajax 和 PHP 更新数据。以下脚本更新数据,但运行时间过长。 PHP

$groupId = $_POST['group_id'];
$Id_array = $_POST['Id'];
$result_array = $_POST['result'];

$data = array();
if(count($_POST['data']) > 0 && !empty ($_POST['data'])){  
    foreach($_POST['data'] as $key => $array){
        $row = array();
        $row['team_id'] = intval($array['team_id']);
        $row['Note'] = strip_tags(trim(strval($array['Note'])));
        $data[$key] = $row;
    }

    for ($i = 0; $i < count($Id_array); $i++) {
        $Id = intval($Id_array[$i]);
        $result = strip_tags(trim(strval($result_array[$i])));

        $sql1 = $db->prepare("UPDATE teams SET result = :result WHERE id = :id ");
        foreach($data as $key => $array){
            $sql1 ->execute(array(':result' => $result, ':id' => $Id));
        }


        $sql2 = $db->prepare("UPDATE teams SET note = :note WHERE team_id = :teamid AND group_id = :group_id");

        foreach($data as $key => $array){
            $sql2->execute(array(':note' => $array['Note'], ':teamid' => $array['team_id'], ':group_id' => $groupId ));
        }

网络时序

【问题讨论】:

  • 您可能需要对每个查询或循环进行一些计时和记录。您一次更新多少行?第一个查询应该进行优化,因为您是按 id 更新的(我猜这是您的主键),但如果您在 team_id 和 group_id 上没有索引,第二个查询可能会很慢。
  • 您能否在不进行第二次查询的情况下执行此脚本?
  • @Shujaat 是的,它不会导致 1 个查询出现问题。
  • @aynber 我在第一次查询时每个 id 更新 1 行,而在 query2 上它应该是多行
  • 尝试将$sql1 = $db-&gt;prepare$sql2 = $db-&gt;prepare 语句移到for(){} 循环之外。您只需要准备一次并执行多次。

标签: php ajax database loops


【解决方案1】:

我会使用事务而不是在循环中自动提交。 所以,

//PDO::beginTransaction ( void )
$dbh->beginTransaction();
foreach () {
    $smt->exec();
}
//PDO::commit ( void )
$dbh->commit();

此外,由于您将变量绑定在执行函数中,因此您只需要准备一次语句,因此请尝试将任何准备语句排除在循环之外。

这应该有助于减少循环中查询的一些开销。

【讨论】:

    【解决方案2】:

    你不需要这个循环:

        foreach($data as $key => $array){
            $sql1 ->execute(array(':result' => $result, ':id' => $Id));
        }
    

    它会重复更新同一个 ID,因为 $Id 在循环中不会改变。做吧:

        $sql1->execute(array(':result' => $result, ':id' => $Id));
    

    一次。

    您还可以通过以下方式获得一些小的改进:

    $sql1 = $db->prepare("UPDATE teams SET result = :result WHERE id = :id ");
    $sql2 = $db->prepare("UPDATE teams SET note = :note WHERE team_id = :teamid AND group_id = :group_id");
    

    只有一次,在任何循环之前。

    另一个问题是你有这个循环:

        foreach($data as $key => $array){
            $sql2->execute(array(':note' => $array['Note'], ':teamid' => $array['team_id'], ':group_id' => $groupId ));
        }
    

    for() 循环内,但它不使用任何在循环中每次都会改变的变量。因此,它正在为$Id_array 中的每个 ID 重新执行所有相同的查询。

    把它排除在循环之外。

    进行所有这些更改后,代码现在如下所示:

    $groupId = $_POST['group_id'];
    $Id_array = $_POST['Id'];
    $result_array = $_POST['result'];
    
    $sql1 = $db->prepare("UPDATE teams SET result = :result WHERE id = :id ");
    $sql2 = $db->prepare("UPDATE teams SET note = :note WHERE team_id = :teamid AND group_id = :group_id");
    
    $data = array();
    if(count($_POST['data']) > 0 && !empty ($_POST['data'])){  
        foreach($_POST['data'] as $key => $array){
            $row = array();
            $row['team_id'] = intval($array['team_id']);
            $row['Note'] = strip_tags(trim(strval($array['Note'])));
            $data[$key] = $row;
        }
    
        foreach ($Id_array as $i => $Id) {
            $Id = intval($Id);
            $result = strip_tags(trim(strval($result_array[$i])));
            $sql1 ->execute(array(':result' => $result, ':id' => $Id));
        }
    
        foreach($data as $key => $array){
            $sql2->execute(array(':note' => $array['Note'], ':teamid' => $array['team_id'], ':group_id' => $groupId ));
        }
    }
    

    【讨论】:

    • 是的,它通过删除 foreach($data as $key =&gt; $array){} 来工作,时间减少了,现在执行需要 2 到 3 秒。还能再改进吗?
    • 所以,你先谴责我的cmets,然后决定从他们那里得到答案,tsk tsk tsk。大声笑,说实话,请 idc 投票
    • @MonkeyZeus 我只是说将 prepare 排除在循环之外是一个小改进,我从未谴责过您的任何其他 cmets。我什至试图澄清其中之一。
    • @KoiToHoga 我已经更新了答案以显示另一个改进,这可能是最大的一个。
    • 是的,谢谢巴尔玛。它对我帮助很大,现在更新不到一秒钟。
    猜你喜欢
    • 2018-01-10
    • 2017-08-04
    • 1970-01-01
    • 1970-01-01
    • 2020-01-01
    • 1970-01-01
    • 2018-01-08
    • 2019-11-14
    • 2012-09-03
    相关资源
    最近更新 更多