Я потратил 4 часа на поиск в Google и пробовал всевозможные индексы, mysqlyog, чтение, поиск и т.д. Я бы очень признателен за помощь. Когда я добавляю GROUP BY, запрос изменяется от 0,002 секунды до 0,093 секунды. Это нормально и приемлемо? Или я могу изменить индексы и/или запрос? Было бы очень полезно помочь. Надеюсь, если я получу ответ, я смогу использовать это знание, двигаясь вперед... спасибо заранее.
Таблица:
uniqueid int(11) NO PRI NULL auto_increment
ip varchar(64) YES NULL
lang varchar(16) YES MUL NULL
timestamp int(11) YES MUL NULL
correct decimal(12,2) YES NULL
user varchar(32) YES NULL
timestart int(11) YES NULL
timeend int(11) YES NULL
speaker varchar(64) YES NULL
postedAnswer int(32) YES NULL
correctAnswerINT int(32) YES NULL
Запрос:
SELECT
SQL_NO_CACHE
user,
lang,
COUNT(*) AS total,
SUM(correct) AS correct,
ROUND(SUM(correct) / COUNT(*) * 100) AS score,
TIMESTAMP
FROM
maths_score
WHERE TIMESTAMP > 1
AND lang = 'es'
GROUP BY USER
ORDER BY (
(SUM(correct) / COUNT(*) * 100) + SUM(correct)
) DESC
LIMIT 500
объясните продлен:
id select_type table type possible_keys key key_len ref rows filtered Extra
------ ----------- ----------- ------ ------------------------- -------------- ------- ------ ------ -------- ---------------------------------------------------------------------
1 SIMPLE maths_score ref scoretable,fulltablething fulltablething 51 const 10631 100.00 Using index condition; Using where; Using temporary; Using filesort
Текущие индексы (я пробовал много)
Keyname Type Unique Packed Column Cardinality Collation Null Comment
uniqueid BTREE Yes No uniqueid 21262 A No
scoretable BTREE No No timestamp 21262 A Yes
lang 21262 A Yes
fulltablething BTREE No No lang 56 A Yes
timestamp 21262 A Yes
user 21262 A Yes
Используйте SHOW CREATE TABLE
; это более описательно, чем DESCRIBE
.
У вас есть INDEX(lang, TIMESTAMP)
? (Почему.) Скорее всего, это поможет обеим версиям запроса.
Без GROUP BY
вы получаете одну строку, правильно? С GROUP BY
вы получаете много строк, правильно? Угадайте, что для большего количества строк требуется больше времени.
Кроме того, GROUP BY
вероятно, включает в себя дополнительный вид. ORDER BY
включает сортировку, но в одном случае сортировка только 1 строки, следовательно, быстрее. Если есть миллион USERs
, тогда ORDER BY
нужно будет сортировать миллион строк, только для доставки 500.
Пожалуйста, предоставьте EXPLAIN SELECT...
для каждого случая - вы увидите некоторые из того, что я говорю.
Таким образом, вы выполнили запрос без GROUP BY
и получили одну строку результатов за 0,002 секунды. Затем вы добавили GROUP BY
(и ORDER BY
явно) и закончили с несколькими строками результата в 0.093 сек.
Чтобы получить этот результат, СУБД должна каким-то образом упорядочить ваши записи пользователем или создать ведра для каждого пользователя, чтобы получить количество записей, сумму и т.д. Для каждого пользователя. Это требует, конечно, гораздо больше времени, чем просто бегать по таблице, подсчитывать записи и суммировать значение безоговорочно. Наконец, СУБД должен снова сортировать эти результаты. Я не удивлен, что это проходит намного дольше.
Наиболее подходящим индексом для этого запроса должно быть:
create index idx on maths_score (lang, timestamp, user, correct);
Это индекс покрытия, начинающийся с столбцов в WHERE
, продолжающийся с столбцом в GROUP BY
и заканчивающийся всеми остальными столбцами, используемыми в запросе.