Vue d’ensemble des projections
Les projections stockent les données dans un format qui optimise l’exécution des requêtes. Cette fonctionnalité est utile pour :- Exécuter des requêtes sur une colonne qui ne fait pas partie de la clé primaire
- Pré-agréger des colonnes afin de réduire à la fois les calculs et les IO
Utilisation du disqueLes projections créent en interne une nouvelle table cachée, ce qui signifie que davantage d’IO et d’espace disque seront nécessaires.
Par exemple, si la projection définit une clé primaire différente, toutes les données de la table d’origine seront dupliquées.
Utilisation des projections
Exemple de filtrage sans utiliser de clés primaires
Création de la table :ALTER TABLE, on peut ajouter la projection à une table existante :
user_name, même si, dans la table d’origine, user_name n’a pas été défini comme PRIMARY_KEY.
Au moment de l’exécution de la requête, ClickHouse détermine que moins de données seront traitées si la projection est utilisée, puisque les données sont ordonnées par user_name.
system.query_log. Dans le champ projections, nous trouvons le nom de la projection utilisée, ou rien si aucune n’a été utilisée :
Exemple de requête de pré-agrégation
Créez la table avec la projectionprojection_visits_by_user :
GROUP BY sur le champ user_agent.
Cette requête n’utilisera pas la projection définie, car la pré-agrégation ne correspond pas.
GROUP BY :
system.query_log pour vérifier si une projection a été utilisée.
Le champ projections indique le nom de la projection utilisée.
Il sera vide si aucune projection n’a été utilisée :
Création et utilisation d’index de projection
Création d’un index de projection :_part_offset conserve sa valeur après les fusions et les mutations, ce qui le rend utile pour l’indexation secondaire. On peut en tirer parti dans les requêtes :
Exemple de projection avec clause WHERE
Les projections peuvent inclure une clause WHERE pour ne stocker qu’un sous-ensemble de lignes. Cela est utile lorsque les requêtes filtrent fréquemment selon un prédicat connu : la projection ne matérialise que les lignes correspondantes, ce qui réduit le stockage et améliore les performances des requêtes.
Création d’une table et ajout d’une projection filtrée :
WHERE d’une requête implique la clause WHERE de la projection (c’est-à-dire que chaque condition du filtre de la projection est également présente dans le filtre de la requête), l’optimiseur peut utiliser automatiquement la projection s’il détermine que cela est bénéfique :
Gestion des projections
Les opérations suivantes sur les projections sont disponibles :ADD PROJECTION
Utilisez l’instruction ci-dessous pour ajouter une description de projection aux métadonnées d’une table :Lorsqu’une projection définit une clause
WHERE, seules les lignes qui correspondent au prédicat sont matérialisées. L’optimiseur peut utiliser une telle projection lorsque la clause WHERE de la requête implique logiquement celle de la projection et que cette projection est avantageuse pour le plan de requête. Cela s’applique aussi bien aux projections normales qu’aux projections d’agrégation.Clause WITH SETTINGS
WITH SETTINGS définit des paramètres de projection qui personnalisent la façon dont la projection stocke les données (par exemple, index_granularity ou index_granularity_bytes).
Ils correspondent directement aux paramètres de table MergeTree, mais s’appliquent uniquement à cette projection.
Exemple :
MODIFY PROJECTION
Utilisez l’instruction ci-dessous pour modifier la clauseWITH SETTINGS d’une projection existante sans reconstruire ses données :
INDEX plutôt que la requête SELECT :
WITH SETTINGS peut différer de la définition existante.
La requête de projection elle-même (ou, pour un index de projection, l’expression et le type de l’index) doit rester identique, car les parts existantes stockent des données construites à partir de celle-ci ; pour la modifier, utilisez DROP PROJECTION, suivi de ADD PROJECTION.
La commande modifie uniquement les métadonnées de la table et ne réécrit aucune donnée : les parts existantes conservent les paramètres avec lesquels elles ont été écrites, tandis que celles créées par de futurs inserts et fusions utilisent les nouveaux paramètres.
MATERIALIZE PROJECTION n’applique pas non plus les nouveaux paramètres aux parts existantes : elle construit la projection uniquement dans les parts où elle est absente ou endommagée, et laisse inchangées les parts de projection déjà existantes.
Pour reconstruire les parts existantes avec les nouveaux paramètres, exécutez CLEAR PROJECTION suivi de MATERIALIZE PROJECTION, ou fusionnez les parts, par exemple avec OPTIMIZE TABLE ... FINAL.
Exemple :
DROP PROJECTION
Utilisez l’instruction ci-dessous pour supprimer la description d’une projection des métadonnées d’une table et supprimer les fichiers de projection sur le disque. Cela est implémenté sous la forme d’une mutation.MATERIALIZE PROJECTION
Utilisez l’instruction ci-dessous pour construire la projectionname dans les parts où elle est manquante ou corrompue, éventuellement uniquement dans la partition partition_name.
Les parts qui contiennent déjà la projection ne sont pas modifiées, même si les paramètres de la projection ont été changés avec MODIFY PROJECTION après leur écriture ; pour les reconstruire, exécutez d’abord CLEAR PROJECTION.
Cette opération est implémentée sous forme de mutation.
CLEAR PROJECTION
Utilisez l’instruction ci-dessous pour supprimer les fichiers de projection sur disque sans supprimer leur description. Cette opération est implémentée sous forme de mutation.ADD, MODIFY, DROP et CLEAR sont légères, au sens où elles ne font que modifier les métadonnées ou supprimer des fichiers.
De plus, elles sont répliquées et synchronisent les métadonnées des projections via ClickHouse Keeper ou ZooKeeper.
La manipulation des projections n’est prise en charge que pour les tables utilisant le moteur
*MergeTree (y compris les variantes répliquées).Contrôler le comportement de fusion des projections
Lorsque vous exécutez une requête, ClickHouse choisit de lire soit dans la table d’origine, soit dans l’une de ses projections. Cette décision est prise individuellement pour chaque part de la table. ClickHouse cherche généralement à lire le moins de données possible et utilise plusieurs techniques pour identifier la meilleure part à lire, par exemple en échantillonnant la clé primaire d’une part. Dans certains cas, des parts de la table source n’ont pas de parts de projection correspondantes. Cela peut se produire, par exemple, parce que la création d’une projection pour une table en SQL est « lazy » par défaut : elle ne s’applique qu’aux données nouvellement insérées et laisse les parts existantes inchangées. Comme l’une des projections contient déjà les valeurs d’agrégation précalculées, ClickHouse essaie de lire les parts de projection correspondantes pour éviter de refaire l’agrégation au moment de l’exécution de la requête. Si une part donnée ne possède pas de part de projection correspondante, l’exécution de la requête revient à la part d’origine. Mais que se passe-t-il si les lignes de la table d’origine changent de manière non triviale à la suite de background merges non triviaux de data parts ? Par exemple, supposons que la table utilise le table engineReplacingMergeTree.
Si la même row est détectée dans plusieurs parts d’entrée lors de la fusion, seule la version la plus récente de la ligne (issue de la part insérée le plus récemment) est conservée, tandis que toutes les versions plus anciennes sont supprimées.
De même, si la table utilise le table engine AggregatingMergeTree, l’opération de fusion peut regrouper des rows identiques dans les parts d’entrée (sur la base des primary key values) en une seule row afin de mettre à jour les partial aggregation states.
Avant ClickHouse v24.8, les parts de projection se désynchronisaient silencieusement des données principales, ou bien certaines opérations comme les mises à jour et les suppressions ne pouvaient pas être exécutées du tout, car la database levait automatiquement une exception si la table avait des projections.
Depuis la v24.8, un nouveau paramètre au niveau de la table deduplicate_merge_projection_mode contrôle le comportement lorsque les background merge operations non triviales mentionnées ci-dessus se produisent dans les parts de la table d’origine.
Les delete mutations sont un autre exemple de part merge operations qui suppriment des rows dans les parts de la table d’origine. Depuis la v24.7, nous disposons également d’un paramètre pour contrôler le comportement vis-à-vis des delete mutations déclenchées par les lightweight deletes : lightweight_mutation_projection_mode.
Voici les valeurs possibles pour deduplicate_merge_projection_mode et lightweight_mutation_projection_mode :
throw(par défaut) : une exception est levée, ce qui empêche les parts de projection de se désynchroniser.drop: les parts de projection affectées sont supprimées. Les requêtes reviennent alors à la part de la table d’origine pour les projections affectées.rebuild: la part de projection affectée est reconstruite afin de rester cohérente avec les données de la part de la table d’origine.
Limites
Il n’est pas possible d’utiliser une colonneALIAS dans la clause ORDER BY d’une projection. Par exemple :
ALIAS ne sont pas stockées physiquement et sont calculées à la volée à l’exécution de la requête. Elles ne sont donc pas disponibles lors de l’écriture de la partie de projection, au moment où l’expression de tri est évaluée.
Utilisez plutôt des colonnes MATERIALIZED ou intégrez directement l’expression :