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


?

873   15  

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 ms

http://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.

сравниваем:

  1. опишите выберите отличное имя продукта от northwind.продукты
  2. опишите 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_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);

или попробовать 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

    Ничего не найдено.