Как сократить время выполнения? - PullRequest
2 голосов
/ 02 октября 2011

У меня есть приложение на 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 && $game['homescore'] > $game['awayscore'])
                    {
                        $points = $points + 1;

                        if (($game['homescore'] - $game['awayscore']) == $bet['diff'])
                            $points = $points + 5;
                    }
                    elseif ($bet['winner'] == 2 && $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 && $game['homescore'] > $game['awayscore'])
                    {
                        $points = $points + 1;

                        if (($game['homescore'] - $game['awayscore']) == $bet['diff'])
                            $points = $points + 5;
                    }
                    elseif ($bet['winner'] == 2 && $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>

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

Ответы [ 3 ]

2 голосов
/ 02 октября 2011

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

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

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

1 голос
/ 23 августа 2012
  1. Пожалуйста, не используйте select *, вместо этого используйте конкретные имена столбцов.
  2. Пожалуйста, избегайте вложенных операторов SQL, используя одну выборку, и сохраняйте данные в массиве для обхода.
  3. Попробуйте использовать XDebug Profiler, чтобы выяснить, какая часть скрипта требует больше времени для загрузки.
1 голос
/ 02 октября 2011

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...