Qu’est-ce qui est plus rapide, SELECT DISTINCT ou GROUP BY dans MySQL?

Si j’ai une table

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

et je veux obtenir toutes les valeurs uniques du domaine profession , ce qui serait plus rapide (ou recommandé):

 SELECT DISTINCT u.profession FROM users u 

ou

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

?

    Ils sont essentiellement équivalents les uns aux autres (en fait, c’est ainsi que certaines bases de données implémentent DISTINCT sous le capot).

    Si l’un d’eux est plus rapide, ça va être DISTINCT . En effet, même si les deux sont identiques, un optimiseur de requêtes doit prendre en compte le fait que votre GROUP BY ne tire parti d’aucun membre du groupe, mais uniquement de ses clés. DISTINCT rend cela explicite, vous pouvez donc vous en tirer avec un optimiseur légèrement plus bête.

    En cas de doute, testez!

    Si vous avez un index sur la profession , ces deux sont des synonymes.

    Si vous ne le faites pas, utilisez alors DISTINCT .

    GROUP BY dans MySQL sortinge les résultats. Vous pouvez même faire:

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

    et obtenez vos professions sortingées par ordre DESC .

    DISTINCT crée une table temporaire et l’utilise pour stocker les doublons. GROUP BY fait de même, mais sortinge ensuite les résultats distincts.

    Alors

     SELECT DISTINCT u.profession FROM users u 

    est plus rapide si vous n’avez pas d’index sur la profession .

    Optez pour le plus simple et le plus court si vous le pouvez – DISTINCT semble être plus ce que vous recherchez uniquement parce que cela vous donnera EXACTEMENT la réponse dont vous avez besoin et seulement cela!

    Toutes les réponses ci-dessus sont correctes pour le cas de DISTINCT sur une seule colonne vs GROUP BY sur une seule colonne. Chaque moteur de firebase database a sa propre implémentation et ses propres optimisations, et si vous vous souciez de la très petite différence (dans la plupart des cas), alors vous devez tester avec un serveur spécifique ET une version spécifique! Comme les implémentations peuvent changer …

    MAIS, si vous sélectionnez plus d’une colonne dans la requête, le DISTINCT est essentiellement différent! Car dans ce cas, il comparera TOUTES les colonnes de toutes les lignes, au lieu d’une seule colonne.

    Donc, si vous avez quelque chose comme:

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

    C’est une erreur courante de penser que le mot-clé DISTINCT distingue les lignes par la première colonne que vous avez spécifiée, mais le DISTINCT est un mot-clé général de cette manière.

    Donc, les gens à qui vous devez faire attention de ne pas prendre les réponses ci-dessus comme étant corrects pour tous les cas … Vous risquez d’être confus et d’obtenir de mauvais résultats alors que tout ce que vous vouliez était d’optimiser!

    bien distinct peut être plus lent que le groupe à certaines occasions dans les postgres (ne sais pas à propos des autres dbs).

    exemple testé:

     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

    donc sois prudent … 🙂

    Group by est plus coûteux que Distinct car Group by fait un sorting sur le résultat alors que distinct l’évite. Mais si vous voulez que grouper par céder le même résultat que distinct donner un ordre par nul ..

     SELECT DISTINCT u.profession FROM users u 

    est égal à

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

    Il semble que les requêtes ne sont pas exactement les mêmes. Au moins pour MySQL.

    Comparer:

    1. décrivez select nom de produit distinct de northwind.products
    2. décrivez select productname from northwind.products group par nom de produit

    La deuxième requête fournit en outre “Utilisation du port de fichiers” dans Extra.

    Dans MySQL , ” Group By ” utilise une étape supplémentaire: filesort . Je me rends compte que DISTINCT est plus rapide que GROUP BY , et ce fut une surprise.

    (plus d’une note fonctionnelle)

    Il y a des cas où vous devez utiliser GROUP BY, par exemple si vous souhaitez obtenir le nombre d’employés par employeur:

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

    Dans un tel scénario, DISTINCT u.employer ne fonctionne pas correctement. Peut-être y a-t-il un moyen, mais je ne le sais pas. (Si quelqu’un sait comment faire une telle requête avec DISTINCT, veuillez append une note!)

    Si vous n’avez pas à faire de fonctions de groupe (sum, moyenne, etc., si vous voulez append des données numériques à la table), utilisez SELECT DISTINCT. Je pense que c’est plus rapide, mais je n’ai rien à montrer.

    Dans tous les cas, si vous êtes inquiet au sujet de la vitesse, créez un index sur la colonne.

    Après des tests approfondis, nous sums arrivés à la conclusion que GROUP BY est plus rapide

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

    635 total 0.0944 secondes Weergave van records 0 – 29 (635 totaal, requête duurde 0.0484 sec)

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

    635 au total 0,2117 secondes (presque 100% plus lent) Weergave van records 0 – 29 (635 totaal, requête duurde 0.3468 sec)

    Ce n’est pas une règle

    Pour chaque requête …. essayez séparément et regroupez par … comparez le temps nécessaire pour terminer chaque requête et utilisez le plus rapidement ….

    Dans mon projet, j’utilise parfois group by et d’autres distincts

    Voici une approche simple qui affichera les 2 temps écoulés pour chaque requête.

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

    Il affiche simplement le nombre de millisecondes requirejs pour parsingr, comstackr et exécuter chaque instruction comme suit:

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

    SELECT DISTINCT sera toujours identique ou plus rapide qu’un GROUP BY. Sur certains systèmes (Oracle), il peut être optimisé pour être identique à DISTINCT pour la plupart des requêtes. Sur d’autres (tels que SQL Server), il peut être considérablement plus rapide.

    Si le problème le permet, essayez EXISTS, car il est optimisé pour terminer dès qu’un résultat est trouvé (et ne tampon aucune réponse), donc, si vous essayez juste de normaliser les données pour une clause WHERE comme celle-ci

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

    Une réponse plus rapide serait:

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

    Ce n’est pas toujours possible, mais lorsque disponible, vous verrez une réponse plus rapide.