Недавно в своей унаследованной программе я наткнулся на длинный SQL-запрос, объединяющий 8 таблиц и 3 представления. Используя EXPLAIN
, я увидел, что это 7 уникальных ключей и 4 неуникальных ключа. В среднем потребовалось 18 секунд, чтобы извлечь 350 строк (для этого было несколько причин, каждое из этих трех представлений состоит из других представлений для одного). Затем я заметил GROUP BY tableone.id
без какого-либо агрегата. Я удалил это, и теперь он работает в миллисекундах.
Теперь запутанная часть состоит в том, что я затем посмотрел, почему MySQL разрешает использование оператора GROUP BY
без агрегатной функции, и узнал, что это на самом деле метод оптимизации (почему MySQL разрешает запросы "группировать по" БЕЗ агрегатных функций?).
Это было явно не так в моей ситуации. Так почему это так? Когда болтается GROUP BY
помеха, а не оптимизатор?
Предложение GROUP BY
, даже без фактической функции агрегирования, подразумевает дополнительную обработку для СУБД, чтобы проверить, нужно ли агрегировать некоторые записи. Таким образом, усиление, которое вы видите при удалении ненужного GROUP BY
.
Ссылка, которой вы поделились, объясняет, что это несколько неэффективное поведение в MySQL могло быть разработано как способ сократить синтаксис агрегированных запросов, где группировка по одному полю подразумевала бы, что другие поля также группируются, и, возможно, также как оптимизация. В любом случае, это не совсем соответствует вашему варианту использования, где вам на самом деле не нужна агрегация.
Использование группы без функции агрегирования больше не допускается, начиная с mysql 5.6 (по понятным причинам.
Для версий более ранних версий затем 5.7 групповое предложение работает, извлекая (причинно-следственное) значение для всех столбцов, не входящих в агрегированную функцию. В противном случае это непредсказуемый результат для этих столбцов. Создайте необходимость работы для сканирования всех строк и извлечения результат с ухудшением производительности.