1

我正在用 php 构建一个用于足球俱乐部的在线工具。该系统的一部分是一个比赛模块,您可以在其中进行视频分析、给球员打分等等。

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

我当前的数据库看起来像这样(我删除了所有不必要的字段):http: //i.stack.imgur.com/VZnpC.png

当我从数据库中获取数据后,我有一个像这样的对象: $match->formations[]->positiongroups[]->positions[]->users[]->statgroups[]->stats[]

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

    /*
    *   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;
    }

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

4

1 回答 1

0

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

编辑:这是您可以轻松完成并提高性能的示例:

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

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

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:

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);
于 2013-10-18T14:13:24.330 回答