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

編集:簡単に実行してパフォーマンスを向上させることができる例を次に示します。

行ごとに行うよりも、一度に多くのデータを取得することに集中する必要があります。たとえば、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 を 1 つだけ送信します。

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 に答える