Что быстрее, 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 telwerken
WHERE 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 )
Это не всегда возможно, но при наличии вы увидите более быстрый ответ.