MySQL запрос - становится медленным с GROUP BY

0

Я потратил 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
  • 0
    Важно понимать, что ваше предложение 'order by' требует, чтобы mysql сортировал весь вывод до того, как что-либо выдать, потому что это предложение содержит вычисленные значения.
  • 0
    Для повышения производительности одной и той же очереди необходимо создать 3 индекса. (Я думаю, что текущая индексация неверна). 1- Индекс1 на TIMESTAMP + lang 2- Индекс2 на USER и 3- Индекс3 на правильном. Примечание: последовательность столбцов в индексе имеет значение.
Теги:
performance
indexing
mysqli
group-by

2 ответа

1

Используйте SHOW CREATE TABLE; это более описательно, чем DESCRIBE.

У вас есть INDEX(lang, TIMESTAMP)? (Почему.) Скорее всего, это поможет обеим версиям запроса.

Без GROUP BY вы получаете одну строку, правильно? С GROUP BY вы получаете много строк, правильно? Угадайте, что для большего количества строк требуется больше времени.

Кроме того, GROUP BY вероятно, включает в себя дополнительный вид. ORDER BY включает сортировку, но в одном случае сортировка только 1 строки, следовательно, быстрее. Если есть миллион USERs, тогда ORDER BY нужно будет сортировать миллион строк, только для доставки 500.

Пожалуйста, предоставьте EXPLAIN SELECT... для каждого случая - вы увидите некоторые из того, что я говорю.

0

Таким образом, вы выполнили запрос без GROUP BY и получили одну строку результатов за 0,002 секунды. Затем вы добавили GROUP BYORDER BY явно) и закончили с несколькими строками результата в 0.093 сек.

Чтобы получить этот результат, СУБД должна каким-то образом упорядочить ваши записи пользователем или создать ведра для каждого пользователя, чтобы получить количество записей, сумму и т.д. Для каждого пользователя. Это требует, конечно, гораздо больше времени, чем просто бегать по таблице, подсчитывать записи и суммировать значение безоговорочно. Наконец, СУБД должен снова сортировать эти результаты. Я не удивлен, что это проходит намного дольше.

Наиболее подходящим индексом для этого запроса должно быть:

create index idx on maths_score (lang, timestamp, user, correct);

Это индекс покрытия, начинающийся с столбцов в WHERE, продолжающийся с столбцом в GROUP BY и заканчивающийся всеми остальными столбцами, используемыми в запросе.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню