MySQL не использовал индекс в SUM с запросом GROUP BY

0

Я просто создал таблицу с:

CREATE TABLE 'table_test' (
'time' date NOT NULL,
'line_id' char(36) NOT NULL,
'location_id' char(36) NOT NULL,
'placement_id' char(36) NOT NULL,
'flight_id' char(36) NOT NULL,
'impressions' int(11) DEFAULT '0',
PRIMARY KEY ('time','line_id','location_id','placement_id','flight_id'),
KEY 'table_test_IDX' ('time','placement_id','line_id','impressions') USING 
BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8

Затем, когда я пытаюсь выполнить запрос:

SELECT 
  time,
  placement_id,
  line_id,
  SUM(impressions) AS totalImpress
FROM
  table_test
WHERE
  time BETWEEN '2017-11-01' AND '2017-11-30'
GROUP BY time , placement_id , line_id;

Он всегда использует Using where; Using temporary; Using filesort Using where; Using temporary; Using filesort Using where; Using temporary; Using filesort, в этом случае я хочу, чтобы запрос использовал table_test_IDX.

Что я сделал здесь неправильно?

Большое спасибо.

Теги:
performance
indexing
sum
query-optimization

2 ответа

0

Предполагаю, вы используете UUID? Измените CHAR(36) на CHAR(36) CHARACTER SET ascii. Лучше было бы упаковать их в BINARY (16). (См. Http://mysql.rjweb.org/doc.php/uuid.) Это уменьшает размер от 108 до 36 до 16.

Вы говорите, что использует filesort и т.д., Но использует ли PRIMARY? Предоставьте EXPLAIN SELECT...

Но, чтобы еще быстрее ускорить работу, подумайте о создании и обслуживании "Сводной таблицы (таблиц)". (См. Http://mysql.rjweb.org/doc.php/summarytables.) Если у вас была одна строка в сводной таблице за комбо (time, placement_id, line_id), GROUP BY и SUM могли быть удалены. (Если вы суммируете по часам, вам все равно нужны.)

0

Если вы будете изучать документацию MySQL для оптимизации запросов агрегирования, вы обнаружите, что существует два метода оптимизации запроса GROUP BY, а именно: рыхлые и плотные проверки индексов. Тем не менее, одна оговорка для любого из этих сканов заключается в том, что единственными агрегатными функциями, используемыми в списке выбора, являются MIN или MAX. Поскольку вы выбираете SUM, эти оптимизации недоступны.

Имеет смысл использовать индекс, который может принести пользу вашему WHERE, поскольку это может позволить нам отбросить записи из набора результатов на ранней стадии в плане запроса. Однако для вычисления суммы для каждой группы MySQL должен касаться каждой записи в оставшейся таблице. Нет никакого способа обойти это, чтобы получить сумму, поэтому не имеет никакого значения, как мы обращаемся ко всем этим записям.

  • 0
    Спасибо Тим за ваш ответ. Но мне интересно, когда я пытаюсь выполнить запрос с этой опцией: USE INDEX(table_test_IDX) . Время запроса быстрее в 2 раза, чем обычно.
  • 0
    Да, но в какой точке запроса используется этот индекс? Оптимизатор не всегда делает все правильно. Если у вас достаточно небольшой набор данных с разумным временем выполнения, я бы не стал слишком много анализировать; в большинстве случаев оптимизатор умнее вас.

Ещё вопросы

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