Что быстрее, выберите 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 существенно отличается! Потому что в этом случае он будет сравнить все столбцы всех строк, а не только один столбец.
Так что если у вас есть что-то вроде:
// 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 является общим ключевым словом таким образом.
Так что люди, Вы должны быть осторожны, чтобы не принимать ответы выше, Как правильно для всех случаев... Вы можете запутаться и получить неправильные результаты, в то время как все, что вы хотели, было оптимизируйте!
ну 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 mshttp://www.pgsql.cz/index.php/PostgreSQL_SQL_Tricks_I
Так что будьте осторожны ... :)
Group by стоит дороже, чем Distinct, так как Group by выполняет сортировку по результату, а distinct избегает его. Но если вы хотите сделать group by, то получите тот же результат, что и distinct give order by null ..
SELECT DISTINCT u.profession FROM users uравна
SELECT u.profession FROM users u GROUP BY u.profession order by null
кажется, что запросы не совсем совпадают. По крайней мере для MySQL.
сравниваем:
- опишите выберите отличное имя продукта от northwind.продукты
- опишите select productname from northwind.группа изделий Марка
второй запрос дает дополнительно "Using 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в группе (7,8,9,10,11,12,13) по opnamegroep_intern635 totaal 0.0944 сек Weergave van records 0-29 (635 totaal, query duurde 0.0484 sec)
выберите sql_no_cache distinct (opnamegroep_intern) От
telwerkenГдеopnemergroepIN (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);или попробовать SET STATISTICS TIME (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.
выбор DISTINCT всегда будет одинаковым или быстрее, чем группа 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 )это не всегда возможно, но при наличии вы увидите более быстрый ответ.
Comments