SELECT DISTINCT est spécifié, seules les lignes uniques apparaissent dans le résultat d’une requête. Ainsi, parmi chaque ensemble de lignes parfaitement identiques dans le résultat, une seule est conservée.
Vous pouvez spécifier la liste des colonnes dont les valeurs doivent être uniques : SELECT DISTINCT ON (column1, column2,...). Si les colonnes ne sont pas spécifiées, elles sont toutes prises en compte.
Considérez la table :
DISTINCT sans spécifier de colonnes :
DISTINCT avec des colonnes spécifiques :
DISTINCT et ORDER BY
ClickHouse permet d’utiliser les clausesDISTINCT et ORDER BY sur des colonnes différentes dans une même requête. La clause DISTINCT est exécutée avant la clause ORDER BY.
Considérons la table :
2, 4 a été tronquée avant le tri.
Tenez compte de cette spécificité d’implémentation lors de l’écriture de requêtes.
Traitement de NULL
DISTINCT traite NULL comme si NULL était une valeur spécifique, et NULL==NULL. Autrement dit, dans les résultats de DISTINCT, les différentes combinaisons avec NULL n’apparaissent qu’une seule fois. Cela diffère du traitement de NULL dans la plupart des autres contextes.
Alternatives
Il est possible d’obtenir le même résultat en appliquant GROUP BY sur le même ensemble de valeurs que celui spécifié dans la clauseSELECT, sans utiliser de fonctions d’agrégation. Mais il existe quelques différences par rapport à l’approche GROUP BY :
DISTINCTpeut être appliqué conjointement avecGROUP BY.- Avant le démarrage de l’exécution externe, une requête sans ORDER BY peut s’arrêter dès qu’elle a lu suffisamment de lignes distinctes pour satisfaire LIMIT.
- Avant le démarrage de l’exécution externe et lorsque
ORDER BYest omis, une plageLIMIT ... AFTER ... UNTILsansALLpeut également arrêter la requête dès que la plage est terminée. - Les blocs de données sont affichés au fur et à mesure de leur traitement jusqu’au démarrage de l’exécution externe.
DISTINCT en mémoire externe
DISTINCT peut écrire des données temporaires sur disque afin de traiter des ensembles de valeurs uniques trop
volumineux pour tenir en mémoire. Cela nécessite des E/S disque supplémentaires et peut ralentir les requêtes.
Deux paramètres déterminent le moment où le déversement sur disque commence :
max_bytes_before_external_distinctdéfinit un seuil, en octets, de la mémoire totale de la requête. Sa valeur par défaut est0(désactivé).max_bytes_ratio_before_external_distinctdéfinit une fraction de la mémoire disponible dans les limites fixées par le serveur ou par l’utilisateur, mesurée au début de l’exécution. Sa valeur par défaut est0.5et il reste sans effet si aucune de ces limites ne s’applique.
0 pour désactiver le déversement sur disque.
max_memory_usage n’influe pas sur le ratio. Pour régler le déversement sur disque par rapport à une limite de mémoire de requête,
définissez un seuil absolu inférieur à cette limite. Par exemple, cette requête utilise un seuil de déversement de 16 Mio
avec une limite de mémoire de requête de 256 Mio :
LIMIT satisfait à ce stade peut mettre fin à la requête de façon anticipée.
Une fois le déversement commencé, le reste de l’entrée doit être lu avant que les résultats restants puissent être renvoyés.
Si la requête comporte un ORDER BY, ces résultats sont renvoyés dans l’ordre demandé.
Lorsque DISTINCT traite une entrée triée selon un préfixe de ses clés, il ne déverse pas sur disque. Un grand groupe de lignes
partageant le même préfixe peut toutefois consommer une quantité importante de mémoire.
Comme avec optimize_distinct_in_order, le déversement peut dédupliquer des valeurs à virgule flottante ayant
des représentations binaires différentes mais considérées comme égales, notamment 0.0 et -0.0, ou des valeurs NaN
dont les charges utiles diffèrent.