O que é mais rápido, SELECT DISTINCT ou GROUP BY no MySQL?

Se eu tiver uma mesa

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) ) 

e eu quero obter todos os valores exclusivos do campo de profession , o que seria mais rápido (ou recomendado):

 SELECT DISTINCT u.profession FROM users u 

ou

 SELECT u.profession FROM users u GROUP BY u.profession 

?

Eles são essencialmente equivalentes entre si (na verdade, é assim que alguns bancos de dados implementam DISTINCT sob o capô).

Se um deles for mais rápido, será DISTINCT . Isso ocorre porque, embora os dois sejam iguais, um otimizador de consulta teria que detectar o fato de que seu GROUP BY não está tirando proveito de nenhum membro do grupo, apenas de suas chaves. DISTINCT torna isso explícito, para que você possa usar um otimizador um pouco mais burro.

Em caso de dúvida, teste!

Se você tem um índice de profession , esses dois são sinônimos.

Se você não fizer isso, use DISTINCT .

GROUP BY no MySQL classifica os resultados. Você pode até fazer:

 SELECT u.profession FROM users u GROUP BY u.profession DESC 

e tenha suas profissões classificadas na ordem DESC .

DISTINCT cria uma tabela temporária e a usa para armazenar duplicatas. GROUP BY faz o mesmo, mas classifica os resultados distintos depois.

assim

 SELECT DISTINCT u.profession FROM users u 

é mais rápido, se você não tiver um índice de profession .

Ir para o mais simples e mais curto, se puder – DISTINCT parece ser mais o que você está procurando apenas porque lhe dará exatamente a resposta que você precisa e só isso!

Todas as respostas acima estão corretas, para o caso de DISTINCT em uma única coluna vs GROUP BY em uma única coluna. Todo mecanismo de db tem sua própria implementação e otimizações, e se você se preocupa com a pequena diferença (na maioria dos casos), então você tem que testar contra um servidor específico E uma versão específica! Como implementações podem mudar …

MAS, se você selecionar mais de uma coluna na consulta, o DISTINCT será essencialmente diferente! Porque neste caso ele irá comparar todas as colunas de todas as linhas, em vez de apenas uma coluna.

Então, se você tem algo como:

 // 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 

É um erro comum pensar que a palavra-chave DISTINCT distingue as linhas pela primeira coluna que você especificou, mas o DISTINCT é uma palavra-chave geral dessa maneira.

Então, as pessoas têm que ter cuidado para não tomar as respostas acima como corretas para todos os casos … Você pode ficar confuso e obter os resultados errados, enquanto tudo que você queria era otimizar!

bem distinto pode ser mais lento do que o grupo em algumas ocasiões em postgres (não sei sobre outros dbs).

exemplo testado:

 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

por isso tem cuidado … 🙂

Agrupar por é caro do que Distinto, já que o Group by faz um tipo de resultado, enquanto distinto o evita. Mas se você quiser fazer o grupo por rendimento o mesmo resultado como distinto dar ordem por nulo ..

 SELECT DISTINCT u.profession FROM users u 

é igual a

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

Parece que as consultas não são exatamente as mesmas. Pelo menos para o MySQL.

Comparar:

  1. descreva select productname distinto de northwind.products
  2. descreva select productname do grupo northwind.products por productname

A segunda consulta fornece adicionalmente “Using filesort” em Extra.

No MySQL , ” Group By ” usa uma etapa extra: filesort . Eu percebo que DISTINCT é mais rápido que o GROUP BY , e isso foi uma surpresa.

(mais de uma nota funcional)

Há casos em que você precisa usar o GROUP BY, por exemplo, se quiser obter o número de funcionários por empregador:

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

Nesse cenário, DISTINCT u.employer não funciona corretamente. Talvez haja um caminho, mas eu simplesmente não sei. (Se alguém souber como fazer essa consulta com DISTINCT, adicione uma nota!)

Se você não precisa fazer nenhuma function de grupo (sum, média etc, caso queira adicionar dados numéricos à tabela), use SELECT DISTINCT. Eu suspeito que seja mais rápido, mas não tenho nada para mostrar.

Em qualquer caso, se você estiver preocupado com a velocidade, crie um índice na coluna.

Após testes pesados, chegamos à conclusão de que o GROUP BY é mais rápido

SELECT sql_no_cache opnamegroep_intern FROM telwerken WHERE opnemergroep IN (7,8,9,10,11,12,13) ​​grupo por opnamegroep_intern

635 totaal 0,0944 segundo Weergave van records 0 – 29 (635 totaal, query duurde 0.0484 sec)

SELECT sql_no_cache distinto (opnamegroep_intern) FROM telwerken WHERE opnemergroep IN (7,8,9,10,11,12,13)

635 totaal 0,2117 segundos (quase 100% mais lento) Weergave van records 0 – 29 (635 totaal, query duurde 0.3468 sec)

Esta não é uma regra

Para cada consulta …. tente separadamente distinto e depois agrupe por … compare o tempo para completar cada consulta e use o mais rápido ….

No meu projeto em algum momento eu uso grupo por e outros distintos

Aqui está uma abordagem simples que irá imprimir os 2 diferentes tempos decorridos para cada consulta.

 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); 

OU tente 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; 

Ele simplesmente exibe o número de milissegundos necessários para analisar, compilar e executar cada declaração, conforme abaixo:

  SQL Server Execution Times: CPU time = 0 ms, elapsed time = 2 ms. 

SELECT DISTINCT será sempre o mesmo ou mais rápido que um GROUP BY. Em alguns sistemas (por exemplo, Oracle), pode ser otimizado para ser o mesmo que DISTINCT para a maioria das consultas. Em outros (como o SQL Server), pode ser consideravelmente mais rápido.

Se o problema permitir, tente com EXISTS, já que ele está otimizado para terminar assim que um resultado for encontrado (E não faça o buffer de nenhuma resposta), portanto, se você estiver apenas tentando normalizar dados para uma cláusula WHERE como esta

 SELECT FROM SOMETHING S WHERE S.ID IN ( SELECT DISTINCT DCR.SOMETHING_ID FROM DIFF_CARDINALITY_RELATIONSHIP DCR ) -- to keep same cardinality 

Uma resposta mais rápida seria:

 SELECT FROM SOMETHING S WHERE EXISTS ( SELECT 1 FROM DIFF_CARDINALITY_RELATIONSHIP DCR WHERE DCR.SOMETHING_ID = S.ID ) 

Isso nem sempre é possível, mas quando disponível, você verá uma resposta mais rápida.