Vue normale
Vue paramétrée
Vue matérialisée
OR REPLACE et IF NOT EXISTS sont mutuellement exclusifs : les combiner provoque une erreur de syntaxe.
CREATE OR REPLACE MATERIALIZED VIEW
CREATE OR REPLACE MATERIALIZED VIEW remplace de manière atomique une vue matérialisée existante ainsi que sa table de stockage interne, s’il y en a une. Cette opération nécessite un moteur de base de données Atomic ou Replicated.
- Sans clause
TO: l’ancienne table interne est supprimée et une nouvelle est créée. Les données existantes de la table interne sont perdues, sauf siPOPULATEest spécifié. - Avec clause
TO: seule la définition de la vue est remplacée ; la table cible et ses données ne sont pas affectées. - Compatible avec
REFRESH,ON CLUSTERet toutes les options de moteur.POPULATEest pris en charge uniquement pour les bases de donnéesAtomic— il est rejeté pour les bases de donnéesReplicated(voir la notePOPULATEci-dessous). - Nécessite les privilèges
CREATE VIEWetDROP VIEW.
CREATE OR REPLACE MATERIALIZED VIEW n’est pris en charge qu’avec les moteurs de base de données Atomic ou Replicated. Il n’est pas pris en charge avec le moteur de base de données Ordinary.TO [db].[table], vous devez spécifier ENGINE — le moteur de table utilisé pour stocker les données.
Lors de la création d’une vue matérialisée avec TO [db].[table], vous ne pouvez pas non plus utiliser POPULATE.
Une vue matérialisée fonctionne comme suit : lors de l’insertion de données dans la table spécifiée dans SELECT, une partie des données insérées est transformée par cette requête SELECT, puis le résultat est inséré dans la vue.
Les vues matérialisées dans ClickHouse utilisent les noms de colonnes plutôt que l’ordre des colonnes lors de l’insertion dans la table de destination. Si certains noms de colonnes ne figurent pas dans le résultat de la requête
SELECT, ClickHouse utilise une valeur par défaut, même si la colonne n’est pas Nullable. Une bonne pratique consiste à ajouter des alias pour chaque colonne lors de l’utilisation de vues matérialisées.Les vues matérialisées dans ClickHouse sont davantage implémentées comme des déclencheurs à l’insertion. S’il y a une agrégation dans la requête de la vue, elle ne s’applique qu’au lot de données nouvellement insérées. Toute modification des données existantes de la table source (comme update, delete, drop partition, etc.) ne modifie pas la vue matérialisée.Les vues matérialisées dans ClickHouse n’ont pas de comportement déterministe en cas d’erreur. Cela signifie que les blocs déjà écrits sont conservés dans la table de destination, mais que tous les blocs suivant l’erreur ne le sont pas.Par défaut, si l’envoi vers l’une des vues génère une exception, la requête INSERT échoue. Rien ne garantit qu’à ce stade le bloc ait déjà atteint la table source — cela dépend du moment où il se trouve dans le pipeline d’insertion, et non de l’erreur de la vue. Réessayez l’INSERT ayant échoué avec la déduplication d’insertion (insert_deduplicate, deduplicate_blocks_in_dependent_materialized_views) pour obtenir une livraison exactly-once vers la table source et toutes les vues dépendantes.Définir materialized_views_ignore_errors=true sur la requête INSERT modifie uniquement le signalement des erreurs : chaque erreur de vue est consignée comme un avertissement et la requête INSERT réussit. La livraison vers la destination de la vue en échec est partielle — les blocs traités avant l’exception sont conservés, et le bloc en échec ainsi que tous les blocs suivants sont ignorés pour cette vue. Les vues en aval de cette destination ne voient que les blocs effectivement arrivés, leur livraison est donc elle aussi partielle. Les vues sœurs (et leurs chaînes en aval) qui n’ont pas généré d’exception sont, elles, écrites intégralement, et la table source est alimentée comme d’habitude. Comme l’INSERT est signalé comme réussi, le client ne reçoit aucun signal d’échec et aucun nouvel essai automatique n’est déclenché ; utilisez ce paramètre uniquement lorsque les écritures dans la table source ne doivent pas être bloquées par des problèmes du côté des vues (par exemple, les tables system.*_log).materialized_views_ignore_errors vaut true par défaut pour les tables system.*_log.POPULATE, les données existantes de la table sont insérées dans la vue lors de sa création, comme avec un CREATE TABLE ... AS SELECT .... Sinon, la requête ne contient que les données insérées dans la table après la création de la vue. Nous ne recommandons pas d’utiliser POPULATE, car les données insérées dans la table pendant la création de la vue n’y seront pas insérées.
Étant donné que
POPULATE fonctionne comme CREATE TABLE ... AS SELECT ..., il présente des limitations :- Il n’est pas pris en charge avec une base de données Replicated
- Il n’est pas pris en charge dans ClickHouse Cloud
INSERT ... SELECT distinct.SELECT peut contenir DISTINCT, GROUP BY, ORDER BY, LIMIT. Notez que les transformations correspondantes sont effectuées indépendamment sur chaque bloc de données insérées. Par exemple, si GROUP BY est défini, les données sont agrégées pendant l’insertion, mais uniquement à l’intérieur d’un seul paquet de données insérées. Les données ne seront pas agrégées davantage. L’exception est l’utilisation d’un ENGINE qui effectue lui-même l’agrégation des données, comme SummingMergeTree.
Si la vue matérialisée utilise la construction TO [db.]name, vous pouvez DETACH la vue, exécuter ALTER sur la table cible, puis ATTACH la vue précédemment détachée (DETACH).
Notez que la vue matérialisée est influencée par le paramètre optimize_on_insert. Les données sont fusionnées avant l’insertion dans une vue.
Les vues se présentent comme des tables normales. Par exemple, elles figurent dans le résultat de la requête SHOW TABLES.
Pour supprimer une vue, utilisez DROP VIEW. Bien que DROP TABLE fonctionne également pour les VIEWs.
Sécurité SQL
DEFINER et SQL SECURITY permettent de spécifier quel utilisateur ClickHouse utiliser lors de l’exécution de la requête sous-jacente de la vue.
SQL SECURITY a trois valeurs possibles : DEFINER, INVOKER ou NONE. Vous pouvez spécifier n’importe quel utilisateur existant ou CURRENT_USER dans la clause DEFINER.
Le tableau suivant indique quels droits sont requis pour quel utilisateur afin d’interroger la vue.
Notez que, quelle que soit l’option de sécurité SQL, il est dans tous les cas nécessaire d’avoir GRANT SELECT ON <view> pour pouvoir la lire.
| Option de sécurité SQL | Vue | Vue matérialisée |
|---|---|---|
DEFINER alice | alice doit disposer du droit SELECT sur la table source de la vue. | alice doit disposer du droit SELECT sur la table source de la vue et du droit INSERT sur la table cible de la vue. |
INVOKER | L’utilisateur doit disposer du droit SELECT sur la table source de la vue. | SQL SECURITY INVOKER ne peut pas être spécifié pour les vues matérialisées. |
NONE | - | - |
SQL SECURITY NONE est une option obsolète. Tout utilisateur disposant des droits pour créer des vues avec SQL SECURITY NONE pourra exécuter n’importe quelle requête arbitraire.
Il est donc nécessaire d’avoir GRANT ALLOW SQL SECURITY NONE TO <user> pour créer une vue avec cette option.DEFINER/SQL SECURITY ne sont pas spécifiés, les valeurs par défaut sont utilisées :
SQL SECURITY:INVOKERpour les vues normales etDEFINERpour les vues matérialisées (configurable dans les paramètres)DEFINER:CURRENT_USER(configurable dans les paramètres)
DEFINER/SQL SECURITY soient spécifiés, la valeur par défaut est SQL SECURITY NONE pour la vue matérialisée et SQL SECURITY INVOKER pour la vue normale.
Pour modifier la sécurité SQL d’une vue existante, utilisez
Exemples
Live View
Vue matérialisée actualisable
interval correspond à une suite d’intervalles simples :
REFRESH doit spécifier au moins l’un des éléments suivants : EVERY, AFTER ou DEPENDS ON. Un REFRESH seul (sans aucun d’eux) est rejeté. REFRESH DEPENDS ON ... sans EVERY/AFTER est une forme abrégée de REFRESH AFTER 0 SECOND DEPENDS ON ... ; voir Dépendances de rafraîchissement ci-dessous.
Exécute périodiquement la requête correspondante et stocke son résultat dans une table.
- Si
APPENDest spécifié, chaque rafraîchissement insère des lignes dans la table sans supprimer les lignes existantes. L’insertion n’est pas atomique, comme pour une requêteINSERT INTO ... SELECTclassique. - Sinon, chaque rafraîchissement remplace atomiquement le contenu précédent de la table.
- Pas de déclencheur d’insertion. Lorsque de nouvelles données sont insérées dans la table spécifiée dans
SELECT, elles ne sont pas automatiquement propagées vers la vue matérialisée actualisable. À la place, l’insertion des données n’a lieu que lors des rafraîchissements périodiques ou manuels. - Aucune restriction sur la requête
SELECT. Les fonctions de table (par ex.url()), les vues, UNION et JOIN sont tous autorisés.
Les paramètres de la partie
REFRESH ... SETTINGS de la requête sont des paramètres de rafraîchissement (par ex. refresh_retries), distincts des paramètres classiques (par ex. max_threads). Les paramètres classiques peuvent être spécifiés à l’aide de SETTINGS à la fin de la requête.Planification du rafraîchissement
RANDOMIZE FOR ajuste aléatoirement le moment de chaque actualisation, par exemple :
REFRESH EVERY 1 MINUTE prend 2 minutes, elle ne sera rafraîchie que toutes les 2 minutes. Si elle devient ensuite plus rapide et commence à se rafraîchir en 10 secondes, elle reviendra à un rafraîchissement toutes les minutes. (En particulier, elle ne se rafraîchira pas toutes les 10 secondes pour rattraper un éventuel retard de rafraîchissements manqués : il n’existe pas de tel retard.)
En général, le premier rafraîchissement démarre immédiatement après la création de la vue matérialisée : le temps écoulé depuis le dernier rafraîchissement est infini, donc toute planification indique qu’il faut la rafraîchir immédiatement. Si EMPTY est spécifié, ce rafraîchissement initial est ignoré, et le premier rafraîchissement a lieu à l’heure planifiée suivante ; par exemple, pour EVERY 1 HOUR, le premier rafraîchissement aura lieu à la fin de l’heure en cours.
Dans une base de données Replicated
APPEND, la coordination peut être désactivée avec SETTINGS all_replicas = 1. Les répliques effectuent alors les rafraîchissements indépendamment les unes des autres. Dans ce cas, ReplicatedMergeTree n’est pas requis.
En mode non-APPEND, seul le rafraîchissement coordonné est pris en charge. Pour un fonctionnement non coordonné, utilisez la base de données Atomic et la requête CREATE ... ON CLUSTER pour créer des vues matérialisées actualisables sur toutes les répliques.
La coordination s’effectue via Keeper. Le chemin du znode est déterminé par le paramètre serveur default_replica_path.
Dépendances d’actualisation
DEPENDS ON synchronise l’actualisation de différentes tables :
DEPENDS ON fonctionne uniquement entre des vues matérialisées actualisables. En particulier, si la vue dont elle dépend utilise TO <table>, veillez à utiliser le nom de la vue plutôt que celui de la table. Si la liste DEPENDS ON contient une table ordinaire, une vue non actualisable ou une faute de frappe, la vue ne sera jamais rafraîchie et affichera l’état MissingDependencies dans system.view_refreshes. Les dépendances peuvent être modifiées ou supprimées à l’aide de ALTER ; voir Modification des paramètres de rafraîchissement.Utilisation de DEPENDS ON pour une latence de propagation cohérente
REFRESH EVERY avec la même période, la dépendance s’applique à chaque créneau temporel.
Par exemple, supposons que les vues X et Y utilisent toutes deux REFRESH EVERY 1 HOUR et que Y lit les données de la table de sortie de X. Sans dépendance, Y verrait généralement les données du rafraîchissement de l’heure précédente de X. Avec DEPENDS ON X, le rafraîchissement de 11:00 de Y ne démarrera qu’une fois celui de 11:00 de X terminé.
Utilisation de DEPENDS ON pour le traitement de flux par lots
REFRESH EVERY n’est pas utilisé, la vue dépendante X se rafraîchit si toutes ses dépendances ont été rafraîchies au moins une fois depuis le dernier rafraîchissement de X. REFRESH AFTER T ajoute un délai : la vue dépendante commencera à se rafraîchir T unités de temps après qu’une dépendance a terminé un rafraîchissement.
Les dépendances circulaires sont autorisées et utiles. Considérez ce graphe de vues matérialisées actualisables :
- X prend un lot de lignes d’un flux et les place dans une table.
- Ensuite, Y et Z lisent tous deux dans cette table, effectuent des agrégations différentes et ajoutent les résultats à d’autres tables.
- Une fois le lot entièrement traité, X prend le lot suivant, et le cycle se répète.
SYSTEM REFRESH VIEW manuel après chaque redémarrage, plutôt qu’une seule fois après la création des vues.
Paramètres de rafraîchissement
refresh_retries- Nombre de tentatives en cas d’échec de la requête de rafraîchissement avec une exception. Si toutes les tentatives échouent, le système passe à l’heure de rafraîchissement planifiée suivante. 0 signifie aucune nouvelle tentative, -1 signifie un nombre infini de tentatives. Par défaut : 2.refresh_retry_initial_backoff_ms- Délai avant la première nouvelle tentative, sirefresh_retriesn’est pas égal à zéro. Chaque tentative suivante double le délai, jusqu’àrefresh_retry_max_backoff_ms. Par défaut : 100 ms.refresh_retry_max_backoff_ms- Limite de la croissance exponentielle du délai entre les tentatives de rafraîchissement. Par défaut : 60000 ms (1 minute).all_replicas- Dans une base de données Replicated avecAPPEND, contrôle si toutes les répliques se rafraîchissent indépendamment ou si une seule réplique se rafraîchit à chaque heure planifiée. Ne peut pas être modifié après la création de la vue. Par défaut :false.
Modification des paramètres de rafraîchissement
ALTER TABLE ... MODIFY REFRESH :
EVERY ou AFTER) est obligatoire : l’instruction remplace toujours tous les paramètres de rafraîchissement — la planification, RANDOMIZE FOR, DEPENDS ON et les paramètres de rafraîchissement — par ceux qui sont spécifiés. Tout élément omis est réinitialisé à sa valeur par défaut (paramètres) ou supprimé (dépendances, randomisation).
-
Pour modifier uniquement les paramètres de rafraîchissement (par ex.
refresh_retries), répétez la planification existante : -
ALTER TABLE ... MODIFY SETTING refresh_retries = ...n’est pas pris en charge pour les vues matérialisées ; vous devez passer parMODIFY REFRESH. -
L’ajout ou la suppression de
APPENDn’est pas pris en charge. -
Le paramètre
all_replicasne peut pas être modifié après la création.
Autres opérations
system.view_refreshes. Elle contient notamment la progression du rafraîchissement (s’il est en cours), la date et l’heure du dernier et du prochain rafraîchissement, ainsi que le message d’exception si un rafraîchissement a échoué.
Pour arrêter, démarrer, déclencher ou annuler manuellement des rafraîchissements, utilisez SYSTEM STOP|START|REFRESH|WAIT|CANCEL VIEW.
Pour attendre la fin d’un rafraîchissement, utilisez SYSTEM WAIT VIEW. C’est notamment utile pour attendre le rafraîchissement initial après la création d’une vue.
Fait amusant : la requête de rafraîchissement peut lire dans la vue en cours de rafraîchissement et voir la version des données antérieure au rafraîchissement. Cela signifie que vous pouvez implémenter le jeu de la vie de Conway : https://pastila.nl/?00021a4b/d6156ff819c83d490ad2dcec05676865#O0LGWTO7maUQIA4AcGUtlA==
Window View
Il s’agit d’une fonctionnalité expérimentale qui pourra évoluer de manière non compatible avec les versions antérieures dans les versions ultérieures. Pour utiliser les window views et la requête
WATCH, activez le paramètre allow_experimental_window_view. Saisissez la commande set allow_experimental_window_view = 1.MATERIALIZED VIEW. Une window view nécessite un moteur de stockage interne pour stocker les données intermédiaires. Le stockage interne peut être spécifié à l’aide de la clause INNER ENGINE ; la window view utilisera AggregatingMergeTree comme moteur interne par défaut.
Lors de la création d’une window view sans TO [db].[table], vous devez spécifier ENGINE – le moteur de table utilisé pour stocker les données.
Fonctions de fenêtre temporelle
ATTRIBUTS TEMPORELS
time_attr de la fonction de fenêtre temporelle une colonne de table, ou en utilisant la fonction now(). La requête suivante crée une window view avec le temps de traitement.
WATERMARK.
Window view propose trois stratégies de watermark :
STRICTLY_ASCENDING: émet un watermark correspondant à l’horodatage maximal observé jusqu’à présent. Les lignes dont l’horodatage est inférieur à l’horodatage maximal ne sont pas considérées comme en retard.ASCENDING: émet un watermark correspondant à l’horodatage maximal observé jusqu’à présent moins 1. Les lignes dont l’horodatage est égal ou inférieur à l’horodatage maximal ne sont pas considérées comme en retard.BOUNDED: WATERMARK=INTERVAL. Émet des watermarks correspondant à l’horodatage maximal observé moins le délai spécifié.
WATERMARK :
ALLOWED_LATENESS=INTERVAL. Voici un exemple de gestion du retard :
SELECT spécifiée dans la window view à l’aide de l’instruction ALTER TABLE ... MODIFY QUERY. La structure de données résultant de la nouvelle requête SELECT doit être identique à celle de la requête SELECT d’origine, avec ou sans la clause TO [db.]name. Notez que les données de la fenêtre en cours seront perdues, car l’état intermédiaire ne peut pas être réutilisé.
Surveillance des nouvelles fenêtres
TO pour écrire les résultats dans une table.
LIMIT pour définir le nombre de mises à jour à recevoir avant de mettre fin à la requête. La clause EVENTS permet d’obtenir une forme abrégée de la requête WATCH : au lieu du résultat de la requête, vous ne recevrez que son watermark le plus récent.
Paramètres
window_view_clean_interval: intervalle de nettoyage de la window view, en secondes, pour libérer les données obsolètes. Le système conserve les fenêtres qui n’ont pas encore été entièrement déclenchées en fonction de l’heure système ou de la configurationWATERMARK, et supprime les autres données.window_view_heartbeat_interval: intervalle de heartbeat, en secondes, indiquant que la requête watch est active.wait_for_window_view_fire_signal_timeout: délai d’attente du signal de déclenchement de la window view lors du traitement en temps d’événement.
Exemple
data, dont la structure est la suivante :
WATCH pour obtenir les résultats.
data,
WATCH devrait afficher les résultats comme ceci :
TO.
*window_view*).
Utilisation de Window View
- Surveillance : agréger et calculer les métriques des logs au fil du temps, puis envoyer les résultats vers une table cible. Le tableau de bord peut utiliser la table cible comme table source.
- Analyse : agréger et prétraiter automatiquement les données dans la fenêtre temporelle. Cela peut être utile lors de l’analyse d’un grand nombre de logs. Ce prétraitement élimine les calculs répétés dans plusieurs requêtes et réduit la latence des requêtes.
- Blog : Travailler avec des données de séries temporelles dans ClickHouse
- Blog : Créer une solution d’observabilité avec ClickHouse - Partie 2 - Traces
Vues temporaires
- Durée de vie de la session Une vue temporaire n’existe que pendant la session en cours. Elle est supprimée automatiquement à la fin de la session.
- Aucune base de données Vous ne pouvez pas qualifier une vue temporaire avec un nom de base de données. Elle existe en dehors des bases de données (dans l’espace de noms de la session).
-
Non répliqué / pas de ON CLUSTER
Les objets temporaires sont locaux à la session et ne peuvent pas être créés avec
ON CLUSTER. - Résolution des noms Si un objet temporaire (table ou vue) porte le même nom qu’un objet persistant et qu’une requête fait référence à ce nom sans base de données, c’est l’objet temporaire qui est utilisé.
-
Objet logique (pas de stockage)
Une vue temporaire stocke uniquement son texte
SELECT(en utilisant le moteurViewen interne). Elle ne conserve pas les données et n’accepte pasINSERT. -
Clause ENGINE
Vous n’avez pas besoin de spécifier
ENGINE; s’il est fourni sous la formeENGINE = View, il est ignoré ou traité comme la même vue logique. -
Sécurité / privilèges
La création d’une vue temporaire nécessite le privilège
CREATE TEMPORARY VIEW, implicitement accordé parCREATE VIEW. -
SHOW CREATE
Utilisez
SHOW CREATE TEMPORARY VIEW view_name;pour afficher le DDL d’une vue temporaire.
Syntaxe
OR REPLACE n’est pas pris en charge pour les vues temporaires (comme pour les tables temporaires). Si vous devez « remplacer » une vue temporaire, supprimez-la, puis recréez-la.
Exemples
Restrictions / limites
CREATE OR REPLACE TEMPORARY VIEW ...→ non autorisé (utilisezDROP+CREATE).CREATE TEMPORARY MATERIALIZED VIEW .../WINDOW VIEW→ non autorisé.CREATE TEMPORARY VIEW db.view AS ...→ non autorisé (pas de qualificatif de base de données).CREATE TEMPORARY VIEW view ON CLUSTER 'name' AS ...→ non autorisé (les objets temporaires sont locaux à la session).POPULATE,REFRESH,TO [db.table], les moteurs internes et toutes les clauses propres aux MV → non applicables aux vues temporaires.
Remarques sur les requêtes distribuées
Memory), leurs données peuvent être envoyées vers des serveurs distants lors de l’exécution distribuée des requêtes, de la même manière que pour les tables temporaires.