提高现有功能的性能,Laravel

Improve performance to an existing function , Laravel

我尝试重构我的代码,但这次我的表现很差。目标是获得具有唯一 "answer_id" 的数组列表,并获得一些 "Score"、"Votes" 等等。

在我现有的第一个中,我首先检查 $most_voted 是否为空,如果是,我分配第一个元素,然后我将在第二个 foreach 中插入一个新元素,或者我更新现有元素。但是从我的第二个 foreach 开始,我就过得很糟糕。关于这个逻辑有什么建议吗?

$answers = $history->toArray(); //here I have an array of arrays
$most_voted = [];

foreach ($answers as $key => $answer) {

    if (!empty($most_voted) ) {

        // in this if I create new arrays or I update existing ones 
        foreach ($most_voted as $k => $v) {
            //If value already exists, increase Votes/Score/Percentage
            if (intval($most_voted[$k]['answer_id']) === intval($answer['lkp_answer_id'])) {

                $most_voted[$k]['Votes'] = $most_voted[$k]['Votes'] + 1;
                $most_voted[$k]['Score'] = $most_voted[$k]['Score'] + $answer['score'];
                $most_voted[$k]['Percentage'] = substr((($most_voted[$k]['Votes'] * 100) / $votes), 0, 5);
                $most_voted[$k]['Weight'] = substr((($most_voted[$k]['Score'] * 100) / $total_scoring), 0, 5);

                //Else add new array element
            } else {
                $name = LkpAnswer::where('id', '=', $answer['lkp_answer_id'])->pluck('name');
                (isset($name[0]) && $name[0] !== null) ? $name = $name[0] : '';                

                if(! empty($answer['lkp_answer_id'])){

                    $most_voted[$key] = [
                        'answer_id' => $answer['lkp_answer_id'],
                        'Name' => $name,
                        'Votes' => 1,
                        'Score' => $answer['score'],
                        'Percentage' => substr(((1 * 100) / $votes), 0, 5),
                        'Weight' => substr((($answer['score'] * 100) / $total_scoring), 0, 5),
                    ];
                }
            }
        }
    } else {
        $name = LkpAnswer::where('id', '=', $answer['lkp_answer_id'])->pluck('name');
        (isset($name[0]) && $name[0] !== '') ? $name = $name[0] : '';
        //If $most_voted is null, insert first value
        $most_voted[$key] = [
            'answer_id' => $answer['lkp_answer_id'],
            'Name' => $name,
            'Votes' => 1,
            'Score' => $answer['score'],
            'Percentage' => substr(((1 * 100) / $votes), 0, 5),
            'Weight' => substr((($answer['score'] * 100) / $total_scoring), 0, 5),
        ];
    }

}

我在这里 dd($answers);

  0 => array:14 [
    "id" => 68
    "user_id" => 57
    "round_number" => 1
    "lkp_answer_id" => 15
    "question_id" => 65
    "paragraph_id" => null
    "answer_time" => 386
    "answer_type" => "none"
    "answer_type_second_menu" => null
    "score" => 1
    "user_score_for_answer" => 2
    "correct_answer_score" => 2
    "created_at" => null
    "updated_at" => null
  ]
  1 => array:14 [
    "id" => 262
    "user_id" => 44
    "round_number" => 1
    "lkp_answer_id" => 26
    "question_id" => 65
    "paragraph_id" => null
    "answer_time" => 716
    "answer_type" => ""
    "answer_type_second_menu" => null
    "score" => 1
    "user_score_for_answer" => 2
    "correct_answer_score" => 1
    "created_at" => null
    "updated_at" => null
  ] //and many more..

优化的第一条规则(在我看来),

从不 运行 在循环内查询。


循环开始前:

// Fetch all data at once and use select() whenever possible
$LkpAnswers = LkpAnswer::whereIn('id', collect($answers)->pluck('lkp_answer_id')->toArray())->select('name')->get();


在你的其他条件下(在第二个循环内)做这样的事情。

// Before, this query was inside 2 for loops (n^2). For every n, there's 1 query.
// This right here is a Collection of LkpAnswer::model. Collection is very useful for optimization
$name = $LkpAnswers->where('id', $answer['lkp_answer_id'])->pluck('name')->toArray();

使用这个并改变你的第二个 else 条件。仅通过这样做,您将节省近 50% 的 运行 时间。另请查看 上的此答案。它讨论了缓存索引select()类型转换.

让我在下面的评论中发布。