Как я могу оптимизировать этот запрос? - PullRequest
1 голос
/ 10 октября 2009

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

SELECT user_id, user_id AS uid, (SELECT correct_words 
                                FROM score 
                                WHERE user_id = `uid` 
                                ORDER BY correct_words DESC, incorrect_words ASC 
                                LIMIT 0, 1) AS correct_words,
                                (SELECT incorrect_words 
                                FROM score 
                                WHERE user_id = `uid` 
                                ORDER BY correct_words DESC, incorrect_words ASC 
                                LIMIT 0, 1) AS incorrect_words
FROM score
WHERE user_id > 0
AND DATE(date_tested) = DATE(NOW())
GROUP BY user_id
ORDER BY correct_words DESC,incorrect_words ASC
LIMIT 0,7

Цель запроса - выбрать максимальный балл для пользователей за этот день, но показать только самый высокий балл оценки этого пользователя вместо всех его баллов (например, если у одного пользователя было 4 Лучшие 10 баллов за этот день, я хочу показать только самый высокий балл этого пользователя и удалить остальные)

Как ни старайся, мне еще предстоит повторить результаты этого запроса любым другим способом. Сейчас его среднее время выполнения составляет около 2 секунд, но я боюсь, что оно может значительно увеличиться по мере увеличения стола.

Есть мысли?

Ответы [ 2 ]

2 голосов
/ 10 октября 2009

попробуйте это:

Подзапрос в основном возвращает набор результатов всех оценок в правильном порядке, а внешний запрос выдает первый случай. При группировке в MySQL столбцы, которые не группируются, возвращают эквивалент FIRST (столбец): значение первого вхождения.

SELECT user_id, correct_words, incorrect_words
FROM
( SELECT user_id, correct_words, incorrect_words
  FROM score
  WHERE user_id>0
  AND DATE(date_tested)=DATE(NOW())
  ORDER BY correct_words DESC,incorrect_words ASC
)
GROUP BY user_id
LIMIT 0,7
1 голос
/ 10 октября 2009

Подзапросы для correct_words и incorrect_words могут действительно убить вашу производительность. В худшем случае MySQL должен выполнять эти запросы для каждой строки, которую он рассматривает (не для каждой строки, которую он возвращает!). Вместо того чтобы использовать скалярные подзапросы, попробуйте переписать запрос, чтобы использовать JOIN -варианты в зависимости от ситуации.

Кроме того, фильтрация по DATE(date_tested)=DATE(NOW()) может препятствовать использованию индекса MySQL. Я не верю, что какая-либо из производственных версий MySQL допускает индексы на основе функций.

Убедитесь, что у вас есть индексы во всех столбцах, которые вы фильтруете, и упорядочите их. MySQL может использовать многостолбцовые индексы, если столбцы отфильтрованы или упорядочены по вашему запросу, например, CREATE INDEX score_correct_incorrect_idx ON score ( correct_words DESC, incorrect_words ASC ); будет индексом-кандидатом, хотя MySQL может отказаться от его использования в зависимости от создаваемого плана выполнения и его оценок размеров таблицы.

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