PHP / 数据库导致性能问题


php / database causes performance issue

我正在用php为足球俱乐部构建一个在线工具。系统的一部分是一个匹配模块,您可以在其中进行视频分析,为玩家评分等等。

一切正常,唯一的问题是初始页面加载的性能。问题背后的原因是数据库以及我从数据库中获取和呈现数据的方式。

当前的数据库如下所示(我删除了所有不必要的字段):https://i.stack.imgur.com/VZnpC.png

当我从数据库中获取完数据后,我有一个这样的对象:$match->阵型[]->阵地组[]->阵地[]->用户[]->统计组[]->统计[]

获取数据的方式需要很多时间(大约 12 秒),我可能完全错了。您可以看到下面的代码。我使用 laravel 4 作为框架,所以大多数代码都不是普通的 php,但我认为当你阅读代码时,你会明白每一行代码的作用。我确实想注意非拉拉维尔解决方案很好!

    /*
    *   Get fullmatch info
    *   Returned value consists of 
    *   $match->formation->positiongroups[]->positions[]->users[]->statgroups[]->stats[]
    */
    public static function fullMatch($id){
        //Get match of given id with formation and team
        $match = Match::where('id', '=', $id)->with('formation', 'team.formation.positions', 'team.category')->first();
        if($match->formation){
            //Set all positiongroups in $match->formation
            $match->formation->positiongroups = Positiongroup::all();
            //Get possible positions
            foreach(Formation::find($match->formation->id)->positions as $position){
                $positions[] = $position->id;
            }
            //Loop through all positiongroups in $match->formation 
            foreach($match->formation->positiongroups as $positiongroup){
                //Set all positions in positiongroups
                $positiongroup->positions = Position::where('positiongroup_id', '=', $positiongroup->id)->whereIn('id', $positions)->get();
                foreach($positiongroup->positions as $position){
                    $position->users = DB::table('formation_position_match_user')
                        ->leftJoin('users', 'user_id', '=', 'users.id')
                        ->where('formation_id', '=', $match->formation->id)
                        ->where('position_id', '=', $position->id)
                        ->where('match_id', '=', $match->id)
                        ->get();
                    foreach($position->users as $user){
                        $user->statgroups = Statgroup::where('video', '=', 1)->with('Stats')->get();
                        $user->stats = DB::table('stat_statdate_user')
                            ->leftJoin('statdates', 'statdate_id', '=', 'statdates.id')
                            ->where('stat_statdate_user.user_id', '=', $user->id)
                            ->groupBy('stat_statdate_user.stat_id')
                            ->orderBy('stat_statdate_user.stat_id')
                            ->get();
                    }
                }
            }
        }
        return $match;
    }

如果需要更多信息,我很乐意将其添加到帖子中。

我还没有看到它产生的查询,但我认为你有太多嵌套的 foreach 循环,并且你向数据库发送了太多查询。应尽量减少查询数。您可以手动完成或使用某些库。例如 NotORM

编辑:以下是您可以轻松执行和提高性能的示例:

您应该专注于一次获取更多数据,而不是逐行获取。例如,将 WHERE 中的一些 = 替换为 IN ();

所以而不是发送很多查询,比如

SELECT * FROM positions WHERE position_group_id = x;
SELECT * FROM positions WHERE position_group_id = y;
SELECT * FROM positions WHERE position_group_id = z;

您只向服务器发送一个选择:

SELECT * FROM positions WHERE position_group_id IN (x, y, z);

你将不得不修改你的代码,但这不会那么困难......我不知道你的 where 方法是如何工作的,以及它是否支持 IN 语句,但如果支持,请做这样的事情:

$position_group_ids  = array();
foreach ($match->formation->positiongroups as $positiongroup) { 
   $position_group_ids[] = $positiongroup->id;
}
$all_positions =  Position::where('positiongroup_id', 'IN', $position_group_ids);