Что быстрее, выберите 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

?

15 ответов


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

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

когда в сомнении, тест!


если у вас есть индекс на 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.


перейти на самый простой и короткий, если вы можете -- DISTINCT, кажется, больше того, что вы ищете только потому, что он даст вам именно тот ответ, который вам нужен, и только это!


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

но, если вы выбираете более одного столбца в запросе, то 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 является общим ключевым словом таким образом.

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


well distinct может быть медленнее, чем group by в некоторых случаях в 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

Так что будьте осторожны ... :)


группы по дороже, чем отличие с группой не на результат, а особым избегает его. Но если вы хотите сделать group BY дать тот же результат, что и distinct give порядок по null ..

SELECT DISTINCT u.profession FROM users u

равна

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

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

сравниваем:

  1. опишите выберите отдельное имя продукта из northwind.продукты
  2. опишите выберите productname из northwind.Products group by productname

второй запрос дает дополнительно "использование filesort" в Extra.


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


(более функциональное Примечание)

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

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

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


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

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


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

выберите sql_no_cache opnamegroep_intern От telwerken Где opnemergroep IN (7,8,9,10,11,12,13) группа по opnamegroep_intern

635 totaal 0.0944 сек Weergave van records 0-29 (635 totaal, query duurde 0.0484 sec)

выберите sql_no_cache distinct (opnamegroep_intern) От 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)


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

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

в моем проекте когда-то я использую group by и другие distinct


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

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.

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


Если проблема позволяет это, попробуйте с 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 )

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