Я работаю над «таблицей лидеров» для веб-приложения, связанного со спортивным событием, которое сообщает о 20 лучших пользователях на основе их оценок по всем их ответам на тест с несколькими вариантами ответов.Он также отображает собственный рейтинг текущего пользователя в таблице лидеров.
Когда это приложение тестируется под нагрузкой, два рассматриваемых запроса становятся очень медленными, тратя много времени в состоянии «Копирование в таблицу tmp» (до20 секунд на запрос).Они в конечном итоге обрабатываются, но в то же время сотни могут складываться.
В изоляции, учитывая разумное количество строк в таблице ответов, каждому запросу требуется около 1 секунды для выполнения (25 000 пользователей, например 200 000 строк в ответах)
Я добавил некоторые индексы в соответствующие таблицы, особенно для столбцов FK и всего, что используется в операторах where.Я также добавил индекс покрытия для userID, answerID в таблице ответов.
Это запрос самой таблицы лидеров
SELECT users.username, sum(questions.points) as score FROM responses
JOIN answers on responses.answerID = answers.answerID
JOIN questions on answers.questionID = questions.questionID
JOIN users on responses.userID = users.userID
WHERE users.username != '' AND answers.isCorrect
GROUP BY users.userID
ORDER BY score DESC
LIMIT 20
Это запрос для получения собственного рейтинга пользователя.в пределах результатов;сначала отдельный запрос получает их оценку, а затем мы подсчитываем, сколько пользователей имеют более высокие оценки.
Select count(*) +1 as rank from (
SELECT users.username, sum(questions.points) as score
FROM responses
JOIN answers on responses.answerID = answers.answerID
JOIN questions on answers.questionID = questions.questionID
JOIN users on responses.userID = users.userID
WHERE users.username != '' AND answers.isCorrect
GROUP BY users.userID
HAVING sum(questions.points) > 2431
ORDER BY score DESC
) as result
Упрощенная схема - это
QUESTIONS
questionID
question
points
ANSWERS (multiple choice answers for question)
answerID
questionID
answer
isCorrect
RESPONSES (the player's choice of answer)
responseID
answerID
userID
Я думаю, что эти запросы выполняются неопределенно разумным способом, но я хотел бы знать, если есть очевидный лучший способ сделать любой из этих, который я не рассмотрел.
Кроме того, есть ли у кого-нибудь мысли о том, почему эти запросы складываются в "Копирование в таблицу tmp""состояние и просто так долго обрабатывать, когда сервер находится под нагрузкой?Я думал, что это может быть создание их на диске, но я вижу, что это отдельное сообщение о состоянии.Я использовал EXPLAIN, но я чувствую, что временная таблица неизбежна при этих запросах;следовательно, вопрос «Копирование в таблицу tmp» занимает столько времени
Ограничения: не показаны, пользователи имеют идентификаторы teamID, а запросы также фильтруются по teamID.Также не показано, есть несколько событий, и эти запросы также могут быть отфильтрованы по eventID.Кроме того, не все вопросы имеют правильный ответ на момент получения ответа.Правильные ответы могут быть назначены в будущем, но в любом случае в конце спортивного события.Система сообщает процент пользователей, выбирающих каждый ответ.Поэтому были рассмотрены различные способы хранения результатов в более агрегированном виде, но они отброшены, поскольку они конфликтуют с одним или несколькими из этих ограничений.
Надеюсь, этого достаточно для продолжения - большое спасибо