Introduction
Fonctionnement de base
- Nom de l’index. Le nom de l’index est utilisé pour créer le fichier d’index dans chaque partition. Il est également requis comme paramètre lors de la suppression ou de la matérialisation de l’index.
- Expression de l’index. L’expression de l’index sert à calculer l’ensemble des valeurs stockées dans l’index. Elle peut être une combinaison de colonnes, d’opérateurs simples et/ou d’un sous-ensemble de fonctions déterminé par le type d’index.
- TYPE. Le type d’index contrôle le calcul qui détermine s’il est possible d’éviter la lecture et l’évaluation de chaque bloc d’index.
- GRANULARITY. Chaque bloc indexé est constitué de GRANULARITY granules. Par exemple, si la granularité de l’index principal de la table est de 8192 lignes et que la granularité de l’index est de 4, chaque “bloc” indexé comptera 32768 lignes.
skp_idx_{index_name}.idx, qui contient les valeurs ordonnées de l’expressionskp_idx_{index_name}.mrk2, qui contient les offsets correspondants dans les fichiers de colonnes de données associés.
my_value sont scannées :
my_value vaut 125 ont été lues et sélectionnées, et comment les lignes suivantes
ont été ignorées sans être lues sur le disque :
Vous pouvez obtenir des informations détaillées sur l’utilisation des index de saut en activant la trace lors de l’exécution des requêtes. Depuis
clickhouse-client, définissez send_logs_level :
Types d’index de saut
minmax
set
texte
hasAnyToken et hasAllTokens, tout en optimisant également les fonctions courantes de recherche textuelle.
Pour plus de détails, consultez la documentation sur l’index de texte ici.
Types de filtres de Bloom
- Le bloom_filter de base, qui prend un seul paramètre facultatif correspondant au taux de « faux positifs » autorisé entre 0 et 1 (si non spécifié, .025 est utilisé).
-
Le tokenbf_v1 spécialisé (Obsolète)). Il prend trois paramètres, tous liés au réglage du filtre de Bloom utilisé : (1) la taille du filtre en octets (des filtres plus grands produisent moins de faux positifs, au prix d’un surcoût de stockage), (2) le nombre de fonctions de hachage appliquées (là encore, un plus grand nombre de fonctions de hachage réduit les faux positifs), et (3) la seed des fonctions de hachage du filtre de Bloom. Consultez le calculateur ici pour plus de détails sur l’effet de ces paramètres sur le fonctionnement du filtre de Bloom.
Cet index fonctionne uniquement avec les types de données String, FixedString et Map. L’expression d’entrée est découpée en séquences de caractères séparées par des caractères non alphanumériques. Par exemple, une valeur de column
This is a candidate for a \"full text\" searchcontiendra les tokensThisisacandidateforfulltextsearch. Il est destiné à être utilisé avec des recherches LIKE, EQUALS, IN, hasToken() et d’autres recherches similaires portant sur des mots et d’autres valeurs au sein de chaînes plus longues. Par exemple, un cas d’usage possible serait la recherche d’un petit nombre de noms de classe ou de numéros de ligne dans une column de lignes de logs applicatifs en texte libre. -
Le ngrambf_v1 spécialisé (Obsolète). Cet index fonctionne de la même manière que l’index de tokens. Il prend un paramètre supplémentaire avant les réglages du filtre de Bloom : la taille des ngrams à indexer. Un ngram est une chaîne de caractères de longueur
ncomposée de caractères quelconques, de sorte que la chaîneA short stringavec une taille de ngram de 4 serait indexée comme suit :
Pour les workloads de recherche en texte intégral, le index de texte dédié (voir Text index for full-text search) est recommandé à la place des index obsolètes tokenbf_v1 ou ngrambf_v1. Le index de texte fournit un véritable index inversé avec de meilleures performances de recherche, un comportement plus prévisible, ainsi qu’une plus grande souplesse et de meilleures performances que les index de filtre de Bloom basés sur des tokens.
Fonctions des index de saut
- des données sont insérées et l’index est défini comme une expression fonctionnelle (le résultat de l’expression étant stocké dans les fichiers d’index), ou
- la requête est traitée et l’expression est appliquée aux valeurs d’index stockées afin de déterminer s’il faut exclure le block.
set et les index basés sur un filtre de Bloom (un autre type d’index set) sont tous deux non ordonnés et ne fonctionnent donc pas avec des plages. À l’inverse, les index minmax sont particulièrement efficaces avec les plages, car il est très rapide de déterminer si des plages s’intersectent. L’efficacité des fonctions de correspondance partielle LIKE, startsWith, endsWith et hasToken dépend du type d’index utilisé, de l’expression d’index et de la structure particulière des données.
Paramètres des index de saut
- use_skip_indexes (0 ou 1, 1 par défaut). Toutes les requêtes ne peuvent pas utiliser efficacement les index de saut. Si une condition de filtrage donnée est susceptible d’inclure la plupart des granules, l’utilisation de l’index de data skipping entraîne un coût inutile, parfois important. Définissez cette valeur sur 0 pour les requêtes qui ne bénéficieront probablement d’aucun index de saut.
- force_data_skipping_indices (liste de noms d’index séparés par des virgules). Ce paramètre peut être utilisé pour empêcher certains types de requêtes inefficaces. Lorsqu’une requête sur une table est trop coûteuse sans index de saut, l’utilisation de ce paramètre avec un ou plusieurs noms d’index renverra une exception pour toute requête qui n’utilise pas les index indiqués. Cela évite que des requêtes mal écrites ne consomment les ressources du serveur.
Bonnes pratiques des index de saut
timestamp et qu’il existe un index sur visitor_id. Considérez la requête suivante :
visitor_id seront testées
quel que soit le type d’index de saut.
Par conséquent, l’idée naturelle de vouloir accélérer les requêtes ClickHouse en ajoutant simplement un index aux
colonnes clés est souvent erronée. Cette fonctionnalité avancée ne doit être utilisée qu’après avoir étudié d’autres solutions, comme modifier la clé primaire (voir Comment choisir une clé primaire), utiliser des projections ou utiliser des vues matérialisées. Même lorsqu’un index de saut de données est approprié, un réglage minutieux de l’index comme de la table
sera souvent nécessaire.
Dans la plupart des cas, un index de saut utile nécessite une forte corrélation entre la clé primaire et la colonne/expression non primaire ciblée.
S’il n’y a pas de corrélation (comme dans le diagramme ci-dessus), il est très probable que la condition de filtrage soit satisfaite par au moins une des lignes du
bloc de plusieurs milliers de valeurs, et peu de blocs seront ignorés. À l’inverse, si une plage de valeurs de la clé primaire (comme le moment de la
journée) est fortement associée aux valeurs de la colonne d’index potentielle (comme l’âge des téléspectateurs), alors un index de type minmax
sera probablement bénéfique. Notez qu’il peut être possible d’augmenter cette corrélation lors de l’insertion des données, soit en incluant des
colonnes supplémentaires dans la clé de tri/ORDER BY, soit en regroupant les inserts de manière à ce que les valeurs associées à la clé primaire soient regroupées à l’insertion. Par
exemple, tous les événements d’un site_id particulier pourraient être regroupés et insérés ensemble par le processus d’ingestion, même si la clé primaire
est un timestamp contenant des événements provenant d’un grand nombre de sites. Cela produira de nombreux granules qui ne contiennent que quelques identifiants de site, de sorte que de nombreux
blocs pourront être ignorés lors d’une recherche sur une valeur site_id spécifique.
Un autre bon candidat pour un index de saut concerne les expressions à cardinalité élevée où une valeur donnée est relativement peu présente dans les données. Un exemple
pourrait être une plateforme d’observabilité qui suit les codes d’erreur dans les requêtes API. Certains codes d’erreur, bien que rares dans les données, peuvent être particulièrement
importants pour les recherches. Un index de saut de type set sur la colonne error_code permettrait d’ignorer la grande majorité des blocs qui ne contiennent pas
d’erreurs et améliorerait donc significativement les requêtes centrées sur les erreurs.
Enfin, la Bonne pratique essentielle est de tester, tester, tester. Là encore, contrairement aux index secondaires b-tree ou aux index inversés pour la recherche dans des documents,
le comportement des index de saut de données n’est pas facile à prédire. Les ajouter à une table entraîne un coût significatif à la fois sur l’ingestion des données et sur les requêtes
qui, pour de nombreuses raisons possibles, ne bénéficient pas de l’index. Ils doivent toujours être testés sur des données réelles, et les tests doivent
inclure des variations de type, de granularité et d’autres paramètres. Les tests révèlent souvent des schémas et des écueils qui ne ressortent pas clairement de
simples raisonnements théoriques.