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

?

+200
источник поделиться
15 ответов

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

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

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

+187
источник

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

+82
источник
другие ответы

Связанные вопросы


Похожие вопросы

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

+17
источник

Все приведенные выше ответы верны, в случае 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 является ключевым словом в этом виде.

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

+12
источник

хорошо различий может быть медленнее, чем группа в некоторых случаях в 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

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

+7
источник

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

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

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

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

+5
источник

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

SELECT DISTINCT u.profession FROM users u

равно

SELECT u.profession FROM users u GROUP BY u.profession order by null
+5
источник

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

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

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

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

+2
источник

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

+2
источник

После тяжелых испытаний мы пришли к выводу, что 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)

+1
источник

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

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

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

+1
источник

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

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.
+1
источник

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

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

0
источник

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

0
источник

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

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

0
источник

Посмотрите другие вопросы по меткам или Задайте вопрос