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