За последние 24 часа нас посетили 26449 программистов и 1545 роботов. Сейчас ищет 821 программист ...

Долго выполняется запрос.

Тема в разделе "MySQL", создана пользователем NightmareZ, 16 янв 2013.

  1. NightmareZ

    NightmareZ Активный пользователь

    С нами с:
    1 мар 2012
    Сообщения:
    62
    Симпатии:
    1
    В статистике хостера увидел, что мой сайт сильно превышает все лимиты на sql-запросы. Оказалось, что вывод одной странички обходится в шесть-семь секунд из-за определённых запросов. Я по-быстрому разобрался с memcached и запилил оптимизацию, но это на данный момент лишь костыль. SQL я пока очень плохо знаю, потому прошу подсказать, что я в запросе неправильно написал:

    Код (Text):
    1. SELECT `id`, `title`, `desc`, `swf`, (SELECT SUM(`rating`) FROM `ratings` WHERE `gameid`=`games`.`id`) / (SELECT COUNT(*) FROM `ratings` WHERE `gameid`=`games`.`id`) AS `rat`, (SELECT COUNT(*) FROM `gameplays` WHERE `gameid`=`games`.`id`) AS `plays` FROM `games` WHERE (`categoryid` LIKE '%1%') ORDER BY `rat` DESC, `plays` DESC LIMIT 0, 26;
    Таблица ratings содержит список оценок, поставленных играм разными пользователями. Таблица gameplays - список айпишников и прочих данных о игравших пользователях. Ну а games - информацию о самих играх.

    Что я делаю (для некоторого categoryid):
    • получаю id игры, чтобы знать, куда перенаправить пользователя
    • получаю title и desc (название и описание игры)
    • считаю rat (рейтинг) игры, деля сумму всех выставленных ей оценок на количество выставленных ей оценок
    • считаю plays (сколько уникальных человек сыграло)
     
  2. runcore

    runcore Старожил

    С нами с:
    12 окт 2012
    Сообщения:
    3.625
    Симпатии:
    158
    на вскидку.
    -проверить если индексы на поля по которым идет выборка и вычисления
    -добавить отдельные поля РЕЙТИНГ и УНИКАЛЬНЫЕ_ИГРОКИ в таблицу ИГРЫ. вычислять и обновлять эти поля в фоне или в момент реального изменения(голосования). тогда не придется их вычислять при запросе, а просто брать готовые значения
     
  3. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    вложенные селекты это смерть. попробуй какнить иначе, вместо считалки при каждой выборке, считай и записывай в поле при обновлении/добавлении.
     
  4. NightmareZ

    NightmareZ Активный пользователь

    С нами с:
    1 мар 2012
    Сообщения:
    62
    Симпатии:
    1
    Спасибо за советы, но мне на данный момент уже удалось добиться удовлетворительных результатов (запрос ускорился минимум в 50 раз), просто перенеся оператор LIMIT.

    Было:
    Код (Text):
    1. SELECT `id`, `title`, `desc`, `swf`, (SELECT SUM(`rating`) FROM `ratings` WHERE `gameid`=`games`.`id`) / (SELECT COUNT(`id`) FROM `ratings` WHERE `gameid`=`games`.`id`) AS `rat`, (SELECT COUNT(`id`) FROM `gameplays` WHERE `gameid`=`games`.`id`) AS `plays` FROM `games` WHERE (`categoryid` LIKE '%1%') ORDER BY `rat` DESC, `plays` DESC LIMIT 0, 26;
    Стало:
    Код (Text):
    1. SELECT `id`, `title`, `desc`, `swf`, (SELECT SUM(`rating`) FROM `ratings` WHERE `gameid`=`games`.`id`) / (SELECT COUNT(`id`) FROM `ratings` WHERE `gameid`=`games`.`id`) AS `rat`, (SELECT COUNT(`id`) FROM `gameplays` WHERE `gameid`=`games`.`id`) AS `plays` FROM (SELECT * FROM `games` LIMIT 0, 26) AS `games` WHERE (`categoryid` LIKE '%1%') ORDER BY `rat` DESC, `plays` DESC;
     
  5. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    если разбить на несколько запросов, тоже станет лучше.
     
  6. Shumomer

    Shumomer Активный пользователь

    С нами с:
    12 мар 2011
    Сообщения:
    194
    Симпатии:
    1
    Адрес:
    из вашего вображения
    Только вот логика запроса изменилась. И результат тоже будет другой. Сейчас, случайно, могло и совпасть.