Как сократить время выполнения?

#php #facebook #facebook-graph-api

#php #Facebook #facebook-graph-api

Вопрос:

У меня есть приложение для Facebook, в котором пользователи могут делать ставки на баскетбольный матч (угадайте победителя, разницу, mvp и лучшего бомбардира).

Я храню одну таблицу с играми, одну с идентификаторами пользователей и одну со ставками.

Если вы угадаете победителя правильно, вы получаете 1 очко. Если вы правильно угадали разницу, вы получаете 5 баллов. Если вы правильно угадали mvp, вы получаете 3 очка, и то же самое касается лучшего бомбардира.

Теперь у меня есть файл, который создает таблицу со всеми пользователями и их точками:

         <table>
        <tr>
            <td></td>
            <td>
                Name
            </td>
            <td>
                Points
            </td>
        </tr>
        <?php
            $selectusers = $db->query("SELECT * FROM `predictorusers`");
            $c = 0;
            while ($appuser = $db->fetchRows($selectusers))
            {
                try
                {
                    $profile = $facebook->api('/'.$appuser['userid']);
                } catch (FacebookApiException $e) {
                    continue;
                }
                $c  ;

                $points = 0;

                $selectbets = $db->query("SELECT * FROM `predictor` WHERE `userid`='{$profile['id']}'");
                while ($bet = $db->fetchRows($selectbets))
                {
                    $selectgame = $db->query("SELECT * FROM `schedule` WHERE `id`='{$bet['gameid']}'");
                    $game = $db->fetchRows($selectgame);

                    if ($bet['winner'] == 1 amp;amp; $game['homescore'] > $game['awayscore'])
                    {
                        $points = $points   1;

                        if (($game['homescore'] - $game['awayscore']) == $bet['diff'])
                            $points = $points   5;
                    }
                    elseif ($bet['winner'] == 2 amp;amp; $game['awayscore'] > $game['homescore'])
                    {
                        $points = $points   1;

                        if (($game['awayscore'] - $game['homescore']) == $bet['diff'])
                            $points = $points   5;
                    }

                    $selectmvprkg = $db->query("SELECT MAX(`rkg`) FROM `boxscore` WHERE `game`='{$game['id']}'");
                    $mvprgk = $db->fetchRows($selectmvprkg);

                    $selectmvp = $db->query("SELECT * FROM `boxscore` WHERE `rkg`='{$mvprkg['rkg']}'");
                    while ($mvp = $db->countRows($selectmvp))
                    {
                        if ($mvp['player'] == $bet['mvp'])
                            $points = $points   3;
                    }

                    $selecttopscorerpts = $db->query("SELECT MAX(`pts`) FROM `boxscore` WHERE `game`='{$game['id']}'");
                    $topscorerpts = $db->fetchRows($selecttopscorerpts);

                    $selecttopscorer = $db->query("SELECT * FROM `boxscore` WHERE `pts`='{$topscorerpts['pts']}'");
                    while ($topscorer = $db->fetchRows($selecttopscorer))
                    {
                        if ($topscorer['player'] == $bet['topscorer'])
                            $points = $points   5;
                    }
                }
        ?>
        <tr>
            <td>
                <?php echo $c; ?>
            </td>
            <td>
                <?php echo $profile['name']; ?>
            </td>
            <td>
                <?php echo $points; ?>
            </td>
        </tr>
        <?php
            }
        ?>
    </table>
  

Единственная проблема заключается в том, что для полного выполнения скрипта требуется более 30 секунд, поэтому сервер останавливает его выполнение и отправляет сообщение об ошибке:

Фатальная ошибка: превышено максимальное время выполнения в 30 секунд в * в строке 37

Кто-нибудь знает, как я могу предотвратить это?

Редактировать:

Взгляните на этот файл, который содержит 0 вызовов api:

         <table>
        <tr>
            <td></td>
            <td>
                Name
            </td>
            <td>
                Points
            </td>
        </tr>
        <?php
            $selectusers = $db->query("SELECT * FROM `predictorusers`");
            $c = 0;
            while ($appuser = $db->fetchRows($selectusers))
            {
                $c  ;

                $points = 0;

                $selectbets = $db->query("SELECT * FROM `predictor` WHERE `userid`='{$appuser['userid']}'");
                while ($bet = $db->fetchRows($selectbets))
                {
                    $selectgame = $db->query("SELECT * FROM `schedule` WHERE `id`='{$bet['gameid']}'");
                    $game = $db->fetchRows($selectgame);

                    if ($bet['winner'] == 1 amp;amp; $game['homescore'] > $game['awayscore'])
                    {
                        $points = $points   1;

                        if (($game['homescore'] - $game['awayscore']) == $bet['diff'])
                            $points = $points   5;
                    }
                    elseif ($bet['winner'] == 2 amp;amp; $game['awayscore'] > $game['homescore'])
                    {
                        $points = $points   1;

                        if (($game['awayscore'] - $game['homescore']) == $bet['diff'])
                            $points = $points   5;
                    }

                    $selectmvprkg = $db->query("SELECT MAX(`rkg`) FROM `boxscore` WHERE `game`='{$game['id']}'");
                    $mvprgk = $db->fetchRows($selectmvprkg);

                    $selectmvp = $db->query("SELECT * FROM `boxscore` WHERE `rkg`='{$mvprkg['rkg']}'");
                    while ($mvp = $db->countRows($selectmvp))
                    {
                        if ($mvp['player'] == $bet['mvp'])
                            $points = $points   3;
                    }

                    $selecttopscorerpts = $db->query("SELECT MAX(`pts`) FROM `boxscore` WHERE `game`='{$game['id']}'");
                    $topscorerpts = $db->fetchRows($selecttopscorerpts);

                    $selecttopscorer = $db->query("SELECT * FROM `boxscore` WHERE `pts`='{$topscorerpts['pts']}'");
                    while ($topscorer = $db->fetchRows($selecttopscorer))
                    {
                        if ($topscorer['player'] == $bet['topscorer'])
                            $points = $points   5;
                    }
                }
        ?>
        <tr>
            <td>
                <?php echo $c; ?>
            </td>
            <td>
                <?php echo $app['userid']; ?>
            </td>
            <td>
                <?php echo $points; ?>
            </td>
        </tr>
        <?php
            }
        ?>
    </table>
  

Происходит то же самое.

Комментарии:

1. изменена строка 18: $profile = $facebook-> api(‘/’.$appuser[‘userid’], array(‘fields’ => ‘name’)); по-прежнему занимает много времени. Я также добавил set_time_limit(0); в начало страницы. Это просто никогда не заканчивается!!!

Ответ №1:

Я бы предложил каким-то образом кэшировать результаты ваших вызовов API, чтобы вам не приходилось вызывать API для каждого пользователя при каждой загрузке страницы.

Вы также можете изучить функции API Facebook, которые позволяют запрашивать данные более чем для одного пользователя одновременно — выполнение одного вызова API для всех пользователей в вашем результирующем наборе будет намного быстрее, чем выполнение отдельных вызовов API для каждого пользователя.

Кроме того, в целом, вложение запросов в циклы на несколько уровней в глубину — плохая идея — попробуйте уменьшить общее количество выполняемых вами запросов.

Комментарии:

1. привет, прежде всего, спасибо за ответ. Во-вторых, пожалуйста, взгляните на мою правку. Спасибо!

Ответ №2:

У вас есть вложенные запросы глубиной 3. Вложенные запросы в коде — это всегда красный флаг (в редких случаях необходимо). Для каждой записи в predictorusers вы запрашиваете записи в predictor. Затем для каждого запроса в predictor вы выполняете запросы по расписанию и boxscore (3 раза).

Вот в чем ваша проблема, у вас слишком много запущенных запросов. Вы должны использовать объединения и сужать данные до конкретной информации. Похоже, вы запрашиваете каждую имеющуюся у вас часть данных. Вероятно, вы можете сократить его до 1 запроса на пользователя или даже просто до 1 запроса с фильтром идентификаторов пользователей.

Комментарии:

1. во-первых, у вас есть опечатка в boxscores mvprgk / mvprkg. Во-вторых, получите все оценки box в одном запросе: ВЫБЕРИТЕ game, MAX(rkg) max_rkg, MAX (pts) max_pts ИЗ ГРУППЫ boxscore ПО игре В-третьих, вы можете присоединиться к чему-то вроде этого: ВЫБЕРИТЕ * ИЗ predictorusers ПРИСОЕДИНИТЬСЯ К predictor НА predictorusers.userid=predictor.userid ПРИСОЕДИНИТЬСЯ К расписанию НА predictor.gameid =schedule.id ЗАКАЗ ПО predictorusers.userid

Ответ №3:

  1. Пожалуйста, не используйте select * , вместо этого используйте конкретные имена столбцов.
  2. Пожалуйста, избегайте вложенных операторов sql, используя одиночную выборку и сохраняйте данные в массиве для обхода.
  3. Попробуйте использовать профилировщик XDebug, чтобы выяснить, какая часть скрипта загружается дольше.