Что быстрее, SELECT DISTINCT или GROUP BY в MySQL?

Если у меня есть таблица

CREATE TABLE users (
  id int(10) unsigned NOT NULL auto_increment,
  name varchar(255) NOT NULL,
  profession varchar(255) NOT NULL,
  employer varchar(255) NOT NULL,
  PRIMARY KEY  (id)
)

и я хочу получить все уникальные значения поля profession, что было бы быстрее (или рекомендовано):

SELECT DISTINCT u.profession FROM users u

или

SELECT u.profession FROM users u GROUP BY u.profession

?

Ответ 1

Они по существу эквивалентны друг другу (на самом деле это то, как некоторые базы данных реализуют DISTINCT под капотом).

Если один из них быстрее, он будет DISTINCT. Это связано с тем, что, хотя оба они одинаковы, оптимизатор запросов должен уловить тот факт, что ваш GROUP BY не использует преимущества каких-либо членов группы, просто их ключи. DISTINCT делает это явным, поэтому вы можете уйти с немного более тупым оптимизатором.

Если вы сомневаетесь, проверьте!

Ответ 2

Если у вас есть индекс на profession, эти два являются синонимами.

Если вы этого не сделаете, используйте DISTINCT.

GROUP BY в MySQL сортирует результаты. Вы даже можете сделать:

SELECT u.profession FROM users u GROUP BY u.profession DESC

и ваши профессии отсортированы в порядке DESC.

DISTINCT создает временную таблицу и использует ее для хранения дубликатов. GROUP BY делает то же самое, но потом сортирует отдельные результаты.

Итак,

SELECT DISTINCT u.profession FROM users u

быстрее, если у вас нет индекса на profession.

Ответ 3

Идём простейшим и самым коротким, если вы можете - DISTINCT, похоже, больше того, что вы ищете, только потому, что он даст вам ТОЧНО ответ, который вам нужен, и только это!

Ответ 4

Все приведенные выше ответы верны, в случае DISTINCT в одном столбце против GROUP BY в одном столбце. Каждый движок db имеет свою собственную реализацию и оптимизацию, и если вы заботитесь о очень небольшой разнице (в большинстве случаев), вам нужно протестировать конкретную версию сервера и конкретной версии! Поскольку реализации могут меняться...

НО, если вы выберете более одного столбца в запросе, то DISTINCT существенно отличается! Потому что в этом случае он будет сравнивать ВСЕ столбцы всех строк, а не только один столбец.

Итак, если у вас есть что-то вроде:

// This will NOT return unique by [id], but unique by (id,name)
SELECT DISTINCT id, name FROM some_query_with_joins

// This will select unique by [id].
SELECT id, name FROM some_query_with_joins GROUP BY id

Общей ошибкой считается мысль о том, что ключевое слово DISTINCT различает строки по указанному первому столбцу, но DISTINCT является ключевым словом в этом виде.

Итак, люди, которым вы должны быть осторожны, чтобы не принимать ответы выше, как правильные для всех случаев... Вы можете запутаться и получить неправильные результаты, пока все, что вы хотели, было оптимизировать!

Ответ 5

хорошо различий может быть медленнее, чем группа в некоторых случаях в postgres (не знаю о других dbs).

Пример

:

postgres=# select count(*) from (select distinct i from g) a;

count 

10001
(1 row)

Time: 1563,109 ms

postgres=# select count(*) from (select i from g group by i) a;

count
10001
(1 row)

Time: 594,481 ms

http://www.pgsql.cz/index.php/PostgreSQL_SQL_Tricks_I

поэтому будьте осторожны...:)

Ответ 6

Кажется, что запросы не совсем одинаковы. По крайней мере, для MySQL.

Для сравнения:

  • Опишите выбранное имя продукта из northwind.products
  • описать select productname из группы northwind.products по имени продукта

Второй запрос дополнительно добавляет "Использование filesort" в Экземпляр.

Ответ 7

Группировка дороже, чем Distinct, так как Group by делает сортировку результата, а отчетливо избегает ее. Но если вы хотите, чтобы группа с уроком получала тот же результат, что и разные, давайте порядок по null..

SELECT DISTINCT u.profession FROM users u

равно

SELECT u.profession FROM users u GROUP BY u.profession order by null

Ответ 8

(больше функциональной заметки)

Есть случаи, когда вам нужно использовать GROUP BY, например, если вы хотите получить количество сотрудников на одного работодателя:

SELECT u.employer, COUNT(u.id) AS "total employees" FROM users u GROUP BY u.employer

В таком сценарии DISTINCT u.employer работает неправильно. Возможно, есть способ, но я просто этого не знаю. (Если кто-то знает, как сделать такой запрос с DISTINCT, добавьте примечание!)

Ответ 9

В MySQL "Group By" использует дополнительный шаг: filesort. Я понимаю, что DISTINCT быстрее, чем Group By, и это было неожиданностью.

Ответ 10

После тяжелых испытаний мы пришли к выводу, что GROUP BY быстрее

SELECT sql_no_cache opnamegroep_intern FROM telwerkenWHERE opnemergroep IN (7,8,9,10,11,12,13) ​​группа by opnamegroep_intern

635 totaal 0,0944 секунды Weergave van records 0 - 29 (635 totaal, query duurde 0.0484 сек)

SELECT sql_no_cache отличный (opnamegroep_intern) FROM telwerkenГДЕ opnemergroep IN (7,8,9,10,11,12,13) ​​

635 totaal 0,2117 секунд (почти на 100% медленнее) Weergave van records 0 - 29 (635 totaal, query duurde 0.3468 sec)

Ответ 11

Это не правило

Для каждого запроса.... попробуйте отдельно различать, а затем группировать по... сравните время, чтобы завершить каждый запрос и использовать быстрее....

В моем проекте когда-то я использую группу by и другие разные

Ответ 12

Вот простой подход, который будет печатать два разных прошедшего времени для каждого запроса.

DECLARE @t1 DATETIME;
DECLARE @t2 DATETIME;

SET @t1 = GETDATE();
SELECT DISTINCT u.profession FROM users u; --Query with DISTINCT
SET @t2 = GETDATE();
PRINT 'Elapsed time (ms): ' + CAST(DATEDIFF(millisecond, @t1, @t2) AS varchar);

SET @t1 = GETDATE();
SELECT u.profession FROM users u GROUP BY u.profession; --Query with GROUP BY
SET @t2 = GETDATE();
PRINT 'Elapsed time (ms): ' + CAST(DATEDIFF(millisecond, @t1, @t2) AS varchar);

ИЛИ попробуйте УСТАНОВИТЬ ВРЕМЯ СТАТИСТИКИ (Transact-SQL)

SET STATISTICS TIME ON;
SELECT DISTINCT u.profession FROM users u; --Query with DISTINCT
SELECT u.profession FROM users u GROUP BY u.profession; --Query with GROUP BY
SET STATISTICS TIME OFF;

Он просто отображает количество миллисекунд, необходимых для синтаксического анализа, компиляции и выполнения каждого оператора, как показано ниже:

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 2 ms.

Ответ 13

Если вам не нужно выполнять какие-либо групповые функции (сумма, среднее значение и т.д., если вы хотите добавить числовые данные в таблицу), используйте SELECT DISTINCT. Я подозреваю, что это быстрее, но мне нечего это показывать.

В любом случае, если вы беспокоитесь о скорости, создайте индекс в столбце.

Ответ 14

SELECT DISTINCT всегда будет тем же или быстрее, чем GROUP BY. В некоторых системах (например, Oracle) оптимизация может быть такой же, как DISTINCT для большинства запросов. В других (например, SQL Server) это может быть значительно быстрее.

Ответ 15

Если проблема позволяет, попробуйте с EXISTS, так как он оптимизирован для завершения, как только результат будет найден (и не буферизуйте какой-либо ответ), поэтому, если вы просто пытаетесь нормализовать данные для предложения WHERE, подобного этому

SELECT FROM SOMETHING S WHERE S.ID IN ( SELECT DISTINCT DCR.SOMETHING_ID FROM DIFF_CARDINALITY_RELATIONSHIP DCR ) -- to keep same cardinality

Более быстрый ответ:

SELECT FROM SOMETHING S WHERE EXISTS ( SELECT 1 FROM DIFF_CARDINALITY_RELATIONSHIP DCR WHERE DCR.SOMETHING_ID = S.ID )

Это не всегда возможно, но при наличии вы увидите более быстрый ответ.