Quand utiliser des dictionnaires plutôt que des JOINs
WHERE. Bien que les versions récentes (24.12+) appliquent les filtres avant les JOINs dans de nombreux cas, cela n’élimine pas toujours ce surcoût. Avec un dictionnaire, vous appelez dictGet directement, de sorte que les lookups ne s’effectuent que sur les lignes qui ont déjà passé le filtrage.
Cependant, dictGet n’est pas toujours le bon choix. Si vous devez appeler dictGet sur un grand pourcentage des lignes d’une table — par exemple, dans une condition WHERE telle que dictGet('dict', 'elevation', id) > 1800 — il peut être préférable d’utiliser une colonne classique avec des index natifs. ClickHouse peut utiliser PREWHERE pour ignorer des granules sur une colonne classique, mais dictGet est évalué ligne par ligne sans prise en charge des index.
En règle générale :
- Utilisez des dictionnaires pour remplacer les JOINs sur de petites tables de dimension lorsque la clé de lookup est déjà disponible.
- Utilisez des colonnes classiques et des index lorsque vous filtrez sur la valeur récupérée sur un grand nombre de lignes.
Choisir un layout
LAYOUT contrôle la structure de données interne du dictionnaire. Tous les layouts disponibles sont documentés dans la référence des layouts.
Lorsque vous choisissez un layout, suivez les recommandations suivantes :
flat— le layout le plus rapide (recherche simple par décalage dans un tableau), mais les clés doivent être de typeUInt64et sont limitées à 500 000 par défaut (max_array_size). Idéal pour des clés entières croissantes monotones dans des tables de petite ou moyenne taille. Les distributions de clés clairsemées (par exemple, des valeurs de clé 1 et 500 000) gaspillent de la mémoire, car le tableau est dimensionné en fonction de la plus grande clé. Si vous atteignez la limite des 500k, c’est généralement le signe qu’il faut passer àhashed_array.hashed_array— le choix par défaut recommandé pour la plupart des cas d’usage. Stocke les attributs dans des tableaux, avec une table de hachage qui associe les clés aux indices des tableaux. Presque aussi rapide quehashed, mais plus économe en mémoire, surtout lorsqu’il y a beaucoup d’attributs.hashed— stocke l’intégralité du dictionnaire dans une table de hachage. Peut être plus rapide quehashed_arraylorsque vous avez très peu d’attributs, mais consomme davantage de mémoire à mesure que leur nombre augmente.complex_key_hashed/complex_key_hashed_array— utilisez-les lorsque les clés ne peuvent pas être converties enUInt64(par exemple, des clésString). Ils présentent les mêmes compromis de performance que leurs équivalents non complexes.sparse_hashed— réduit l’utilisation de la mémoire au prix d’une consommation CPU plus élevée par rapport àhashed. C’est rarement le meilleur choix : il n’est réellement efficace que lorsque vous n’avez qu’un seul attribut. Dans la plupart des cas,hashed_arrayest plus adapté.cache/ssd_cache— ne mettent en cache que les clés fréquemment consultées. Utile lorsque l’ensemble du dataset ne tient pas en mémoire, mais les recherches peuvent interroger la source en cas de cache miss. Non recommandé pour les charges de travail sensibles à la latence.direct— interroge la source à chaque recherche, sans stockage en mémoire. À utiliser lorsque les données changent trop fréquemment pour être mises en cache ou lorsque le dictionnaire est trop volumineux pour tenir en mémoire.
Suivi de l’utilisation des dictionnaires
system.dictionaries :
bytes_allocated— mémoire consommée par le dictionnaire. Les dictionnaires stockent les données non compressées, donc cette valeur peut être nettement supérieure à la taille de la table compressée.hit_rateetfound_rate— utiles pour évaluer l’efficacité du layoutcache.last_exception— vérifiez ce point lorsqu’un dictionnaire ne parvient pas à se charger ou à s’actualiser.