Raisonnement appliqué aux mises en situation
Raisonnement ClickHouse détaillé qui sous-tend les cinq mises en situation du QCM appliqué.
Commencez par les 20 questions appliquées de l'évaluation interactive de la partie 4. Les cinq anciens scénarios rédigés apparaissent maintenant sous la forme de quatre décisions notées chacun. Cette référence conserve les exemples détaillés pour la discussion qui suit l'évaluation.
Scénario 1 — conception du schéma
Modèle de CREATE TABLE
CREATE TABLE IF NOT EXISTS clickstream_events
(
`event_id` UUID CODEC(ZSTD(1)),
`event_time` DateTime64(3) CODEC(Delta, ZSTD(1)),
`event_date` Date DEFAULT toDate(event_time),
`user_id` UUID CODEC(ZSTD(1)),
`session_id` UUID CODEC(ZSTD(1)),
`product_id` String CODEC(ZSTD(1)),
`event_type` LowCardinality(String) CODEC(ZSTD(1)),
`value_usd` Decimal(18, 4) CODEC(ZSTD(1)),
`attributes` Map(LowCardinality(String), String) CODEC(ZSTD(1)),
-- Skip indexes for non-prefix point-lookups
INDEX idx_user_id user_id TYPE bloom_filter(0.01) GRANULARITY 4,
INDEX idx_session_id session_id TYPE bloom_filter(0.01) GRANULARITY 4
)
ENGINE = MergeTree
PARTITION BY event_date
ORDER BY (event_type, product_id, event_time)
TTL event_date + INTERVAL 90 DAY DELETE
SETTINGS ttl_only_drop_parts = 1, index_granularity = 8192;Raisonnement
-
Choix des types :
event_id→UUID(16 octets, contre 36 avec un stockage enString; la colonne est rarement filtrée, elle est seulement conservée).user_id/session_id→UUIDpour la même raison ; une cardinalité d'environ 50 millions / 500 millions exclutLowCardinality.event_type→LowCardinality(String)— 12 valeurs distinctes constituent un cas d'école.Enumserait également possible, maisLowCardinality(String)s'accommode mieux du cas inévitable où quelqu'un ajoute un treizième type d'événement sans redéployer le schéma.product_id→String; environ 2 millions de valeurs distinctes dépassent largement la plage d'utilisation habituelle deLowCardinality(String). Des mesures restent importantes, mais un simpleStringest le choix par défaut le plus défendable.attributes→Map(LowCardinality(String), String)est le choix par défaut sûr pour l'évolution du schéma. Promouvez au fil du temps les clés fréquentes en colonnes MATERIALIZED.value_usd→Decimal(18, 4)pour éviter les erreurs d'arrondi en virgule flottante sur les montants de chiffre d'affaires. Le comportement valeur NULL ou zéro convient ;Nullablen'est pas nécessaire.
-
ORDER BY (event_type, product_id, event_time):- La requête n° 1 (entonnoir par product_id) commence par
WHERE event_type IN ('view','add_to_cart','purchase') AND product_id = X: les deux colonnes du préfixe correspondent, ce qui permet d'éliminer énormément de granules. - La requête n° 3 (chiffre d'affaires par minute) filtre sur
WHERE event_type = 'purchase', donc également sur le préfixe. - La requête n° 2 (historique par utilisateur) n'utilise pas du tout le préfixe : c'est précisément le rôle de l'index de saut
bloom_filtersuruser_id. - Règle d'ordre des cardinalités : faible (12 valeurs) → moyenne (2 millions) → élevée/plage (horodatage). Les premières colonnes à faible cardinalité donnent à l'index davantage de possibilités d'élimination.
- La requête n° 1 (entonnoir par product_id) commence par
-
PARTITION BY event_date:- Une partition par jour ; avec 5 milliards d'événements quotidiens, la partition reste assez grande pour éviter l'antipattern des « milliers de petites partitions ».
- Surtout, cela fait coïncider la partition avec la limite du TTL, de sorte que
ttl_only_drop_parts = 1peut éliminer des partitions entières à faible coût. - Ne partitionnez pas par heure ni par
event_type, car ces deux choix provoqueraient une explosion du nombre de partitions.
-
TTL
event_date + INTERVAL 90 DAY DELETEavecttl_only_drop_parts = 1: supprime en une seule opération les partitions quotidiennes vieilles de 90 jours. Aucune analyse ligne par ligne. -
Index de saut :
bloom_filtersuruser_id(condition de jointure de la requête n° 2) etsession_id(besoin futur probable). N'utilisez pastokenbf_v1ici : il s'agit d'UUID, pas de texte. Une granularité de 4 signifie que chaque filtre de Bloom couvre 4 × 8192, soit environ 32 000 lignes ; ajustez-la en mesurant la latence des recherches. -
AggregatingMergeTree pour la requête n° 3 ? Oui : définissez une MV :
CREATE MATERIALIZED VIEW revenue_by_minute_mv TO revenue_by_minute AS SELECT toStartOfMinute(event_time) AS minute, product_id, sumState(value_usd) AS revenue, countState() AS purchase_count FROM clickstream_events WHERE event_type = 'purchase' GROUP BY minute, product_id;Avec 5 milliards d'événements par jour, les requêtes de tableau de bord sur la table brute seront lentes en situation de contention ; la préagrégation AggMergeTree déplace le coût au moment de l'insertion. La requête n° 1 (entonnoir) et la requête n° 2 (par utilisateur) ne doivent pas recevoir de MV : leur cardinalité est trop forte et elles sont trop variables pour une préagrégation.
Critères de décision
Les questions connexes du QCM valorisent les réponses qui :
- utilisent
MergeTreeavec unORDER BYraisonnable dont le préfixe correspond à la requête n° 1 ou n° 3 (donc ni(event_id, event_time)ni(event_time, …)) ; - partitionnent par date (ou par semaine), et non par event_type ou par heure ;
- utilisent
Map(ou JSON) pourattributes, et non une colonne par attribut ; - comportent au moins un index de saut bloom_filter sur une colonne à forte cardinalité utilisée par la requête n° 2 ;
- incluent une clause TTL alignée sur la limite des partitions.
Un distracteur est incorrect s'il place event_time en premier dans ORDER BY (réflexe courant d'ES qui nuit à ClickHouse) ou s'il partitionne selon autre chose qu'une colonne dérivée de la date.
Scénario 2 — plan de migration
Modèle de plan sur 6 mois
Phase 1 (semaines 1 et 2) : découverte et bac à sable. Déployer un service ClickHouse Cloud de niveau Production dans la même région qu'ES. Provisionner en parallèle un cluster OTel Collector (3 nœuds derrière un répartiteur de charge) qui lit une dérivation du parcours d'ingestion existant ; au départ, il écrit uniquement dans CH et ne reçoit PAS de trafic de production. Objectif : valider la connexion, établir une référence de coûts à 200 000 événements/s en continu et vérifier la gestion de la contre-pression. Critère de sortie : CH ingère 1 heure de données envoyées en double, avec un contrôle d'équivalence (nombre ES contre nombre CH) présentant un écart ≤ 1 %.
Phase 2 (semaines 3 à 6) : conception du schéma et 5 premiers index à forte valeur.
Mettre en correspondance les champs nécessaires aux 5 tableaux de bord Kibana les plus interrogés. Construire des instructions CREATE TABLE qui utilisent par défaut Map(LowCardinality(String), String) pour les plus de 60 champs extraits par grok, tout en matérialisant les 10 champs les plus utilisés (ceux qui sont référencés par au moins 3 tableaux de bord) comme colonnes dédiées. Définir la distribution par vue matérialisée pour toute préagrégation AggregatingMergeTree nécessaire.
Critère de sortie : les requêtes principales des 20 tableaux de bord Kibana disposent toutes d'un équivalent CH opérationnel et renvoient leurs résultats aussi vite qu'ES (ou plus vite).
Phase 3 (semaines 7 à 12) : exécution parallèle et migration des tableaux de bord. Faire passer l'OTel Collector en double écriture (ES + CH). Migrer les tableaux de bord par lots d'environ 50 recherches enregistrées par semaine, en donnant la priorité à ceux qui lisent le plus (plus de 1 To analysé). Exécuter le script de validation deux fois par jour ; examiner tout service dont le nombre d'événements dans ES et CH diverge de plus de 5 %. Critère de sortie : les 300 recherches enregistrées fonctionnent dans CH ; latence p95 ≤ p95 d'ES pendant 7 jours consécutifs.
Phase 4 (semaines 13 à 18) : suppression de Logstash.
Remplacer Logstash par l'OTel Collector. Les plus de 60 motifs grok deviennent des processeurs transform OTel et des colonnes MATERIALIZED CH. (Voir la décision concernant Logstash ci-dessous.) Faire fonctionner Logstash et l'OTel Collector en parallèle pendant 2 semaines ; retirer Logstash une fois l'équivalence établie.
Critère de sortie : aucun trafic ne transite par Logstash pendant 7 jours consécutifs ; les règles d'alerte sont migrées vers les alertes HyperDX (ou un équivalent).
Phase 5 (semaines 19 à 22) : bascule. Arrêter Filebeat → Logstash. Supprimer Logstash. Arrêter l'ingestion de nouvelles données dans ES (tout en conservant le cluster actif et en lecture seule). Toutes les nouvelles données circulent sans ES. Surveiller les tableaux de bord de coûts et la latence des tableaux de bord. Critère de sortie : ES reste en lecture seule pendant 14 jours consécutifs sans ingestion, incident ni demande de retour arrière.
Phase 6 (semaines 23 à 26) : suppression et transfert à l'équipe chargée de la conformité. Créer un dernier instantané complet d'ES vers S3 (opération unique à la date de bascule). Supprimer le cluster ES. Documenter l'emplacement du compartiment S3 pour la conformité et l'audit. Faire évoluer le modèle mental de l'équipe : « ES est la source de vérité » devient « ES est le rétroviseur des 90 derniers jours ». Critère de sortie : le cluster ES est détruit, l'instantané S3 est validé par l'équipe chargée de la conformité et le runbook est mis à jour.
Stratégie de schéma pour plus de 60 champs extraits par grok
- Mois 1 : les 60 champs arrivent tous dans
LogAttributes Map(LowCardinality(String), String). Aucun traitement particulier. - Mois 2 : repérer les 10 champs les plus référencés dans les tableaux de bord. Les promouvoir avec
ALTER TABLE … ADD COLUMN field MATERIALIZED LogAttributes['field']. - Mois 4 : exécuter à nouveau la requête de comptage des références dans les tableaux de bord et promouvoir tout nouveau champ très utilisé. À ce stade, la longue traîne réside dans Map et y reste.
- Mois 6 : réaliser un dernier audit des motifs de requête des tableaux de bord. Le schéma converge généralement vers 15 à 25 colonnes promues, plus la Map pour la longue traîne.
Cette approche évite le piège qui fait échouer les projets de migration : « concevoir d'emblée le schéma parfait ».
Décision concernant Logstash : le remplacer par l'OTel Collector
Les plus de 60 motifs grok constituent le principal facteur de coût de Logstash, tant pour le calcul que pour la complexité opérationnelle. Le processeur transform (OTTL) de l'OTel Collector couvre nativement environ 80 % des cas d'usage de grok ; les 20 % restants deviennent des colonnes MATERIALIZED du schéma cible. Le coût de l'analyse passe ainsi du parcours du collecteur à la couche de stockage, ce qui, dans ClickHouse, signifie un coût d'exécution nul : la valeur analysée est calculée une fois à l'insertion, puis lue gratuitement.
Vector est une solution de remplacement viable. Son langage VRL (Vector Remap Language) est plus familier aux utilisateurs de Logstash, mais il introduit un troisième outil à exploiter. Restons sur l'OTel Collector pour assurer la cohérence de l'écosystème.
Ne conservez pas Logstash. Le fil conducteur de l'atelier consiste à supprimer un outil, et non à remplacer « ES + Logstash + Kibana » par « CH + Logstash + HyperDX ».
Conservation réglementaire (niveau froid d'un an)
CH Cloud ne comporte pas de mécanisme ILM intégré d'instantanés S3, mais deux approches fonctionnent :
- Export quotidien vers un compartiment S3 appartenant au client. Exécutez de façon planifiée
INSERT INTO FUNCTION s3('s3://archive/year/month/day.parquet') SELECT * FROM otel_logs_v2 WHERE event_date = today() - 1. Le compartiment S3 du client conserve un an de données Parquet, qui peuvent être interrogées avec Athena, Trino ou la fonction de tables3()depuis un service CH temporaire. Le stockage coûte environ 23 dollars par To et par mois dans S3 IA, bien moins que le maintien d'un an de données chaudes dans CH. - Utilisation du stockage hiérarchisé de ClickHouse Cloud (lorsqu'il est disponible, généralement au niveau Production chez certains fournisseurs). Le coût du stockage au-delà de 90 jours baisse d'environ 70 %, mais l'audit de conformité est plus complexe qu'avec l'approche S3-Parquet, car les données restent dans CH.
Recommandez l'option (1) pour la conformité : l'auditeur souhaite qu'« afficher tous les journaux d'août 2025 » soit une requête S3 autonome, et non un projet nécessitant de « démarrer un cluster CH ».
Plan de retour arrière si la bascule échoue après 3 semaines
Le retour arrière suppose (a) que vous utilisez déjà la double écriture et (b) qu'une partie des tableaux de bord a été migrée.
- Arrêter les écritures exclusivement destinées à CH : repasser l'OTel Collector en écriture unique dans ES ; CH cesse de croître.
- Rétablir Kibana pour les tableaux de bord : les recherches Kibana enregistrées d'origine existent toujours. Réactivez-les.
- Conserver CH en lecture seule à des fins d'investigation : les données ingérées pendant la période d'exécution parallèle sont utiles pour diagnostiquer l'échec de la bascule.
- Ne pas supprimer les ressources migrées : le nouveau schéma CH, les configurations de l'OTel Collector, etc. sont conservés. Une fois la cause racine corrigée, reprenez à la phase 4 (suppression de Logstash), sans refaire les phases 1 à 3.
Propriété la plus importante de la migration : à tout moment au cours des 5 premières phases, un seul changement de configuration de l'OTel Collector suffit pour revenir à ES.
Trois principaux risques et mesures d'atténuation
- Risque : le schéma est figé trop tôt. Mesure : planifier explicitement une « revue des champs très utilisés » aux mois 2, 4 et 6. Les promotions sont des instructions ALTER TABLE non destructrices.
- Risque : 5 règles d'alerte se comportent différemment dans CH. Mesure : construire les MV d'alerte (voir le module 03, étape 8, option B) à la semaine 8 et les exécuter en mode fantôme pendant 4 semaines avant d'activer les notifications. Comparer leur nombre de déclenchements avec l'historique des alertes Kibana.
- Risque : les motifs grok du client comportent des constructions d'expression régulière non prises en charge. Mesure : répertorier les 60 motifs pendant la première semaine, repérer ceux qui ne sont pas pris en charge (généralement les recherches arrière, les conditions nommées, etc.) et les réécrire en OTTL ou sous forme de colonnes matérialisées CH avec
regexpExtract. Ne pas attendre la semaine 14 pour le découvrir.
Critères de décision
Les questions connexes du QCM valorisent les plans qui :
- comportent des phases claires, chacune assortie d'un critère de sortie ;
- remplacent Logstash par l'OTel Collector (ou Vector) ; conserver Logstash jusqu'à la bascule est éliminatoire ;
- utilisent Map et une promotion sélective pour les 60 champs, au lieu de « créer les 60 colonnes d'emblée » ou d'utiliser « une colonne JSON pour tout » ;
- nomment une méthode précise de conservation réglementaire (export Parquet vers S3, stockage hiérarchisé ou équivalent) ; « nous nous occuperons de la conformité plus tard » est éliminatoire ;
- définissent un parcours de retour arrière qui n'exige pas de réexécuter un import CSV.
Scénario 3 — débogage A (écart de latence p95)
Corrigé type
Les trois causes les plus probables, dans l'ordre :
Cause 1 : les colonnes agrégées n'utilisent pas les mêmes unités.
ES stockait généralement la latence comme un nombre flottant en millisecondes (response_time en secondes × 1000 dans certaines configurations ES, ou déjà en ms). Le champ Duration de ClickHouse pour les traces est exprimé en nanosecondes ; si votre requête CH calcule quantile(0.95)(Duration) sans diviser par 1e6, le résultat sera environ 1000 fois plus grand. Plus subtilement, si votre requête CH lit LogAttributes['run_time'], que l'application émet en secondes, tandis qu'ES disposait déjà d'un champ run_time_ms analysé et converti, les unités diffèrent sans aucun avertissement.
Contrôle : exécutez SELECT min(Duration), max(Duration), avg(Duration) FROM otel_traces et comparez les résultats aux valeurs min/max/avg d'ES pour la même fenêtre. Si les ordres de grandeur diffèrent, les unités sont en cause.
Cause 2 : les algorithmes de centile diffèrent.
L'agrégation percentiles d'Elasticsearch utilise un histogramme HDR ou T-Digest selon la version ; ce sont deux algorithmes approximatifs. quantile() dans ClickHouse est également approximatif (avec un algorithme déterministe, mais différent). Pour des distributions de latence à longue traîne, les deux approximations peuvent diverger de 10 à 25 % malgré des données d'entrée identiques. quantileExact() dans ClickHouse est exact, mais lent ; quantileTDigest() se rapproche davantage d'ES.
Contrôle : exécutez la même requête avec quantileExact(0.95)(Duration) (lent, mais précis). Si la valeur exacte se situe entre les approximations d'ES et de CH, les algorithmes ont simplement employé des stratégies d'estimation des centiles différentes.
Cause 3 : les fenêtres temporelles ou les jeux d'échantillons diffèrent en raison d'une dérive d'horloge ou d'un filtre non équivalent.
La requête CH peut inclure quelques secondes de trafic supplémentaires à l'une ou l'autre extrémité de la fenêtre, car now() - INTERVAL 1 HOUR est évalué à un instant différent de celui de la requête ES, ou parce que la colonne matérialisée TimestampTime est de type DateTime (précision à la seconde), tandis qu'ES filtre sur @timestamp avec une précision à la milliseconde. Avec une longue traîne, un décalage de seulement 5 secondes peut modifier p95 de 20 %.
Contrôle : fixez la fenêtre temporelle avec une clause explicite BETWEEN '2026-05-09 04:00:00' AND '2026-05-09 05:00:00' des deux côtés, puis exécutez à nouveau les requêtes. Si les résultats convergent, l'alignement des périodes était en cause.
Critères de décision
Les questions connexes du QCM valorisent un diagnostic qui comporte :
- une cause liée à la conversion d'unités ou à une incompatibilité de types (Duration en ns contre ms) ;
- soit la différence entre les algorithmes de centile, soit l'alignement des fenêtres temporelles ;
- un contrôle de débogage précis pour chaque cause, et non simplement « examiner le problème ».
Scénario 4 — débogage B (recherche lente d'une clé de Map)
Diagnostic
LogAttributes['request_id'] est un déréférencement de Map à l'exécution : pour chaque ligne analysée, ClickHouse doit rechercher la clé 'request_id' dans la Map. Aucun index de saut n'aide et le stockage colonnaire doit tout de même matérialiser la colonne Map pour chaque ligne de la plage analysée. TraceId, en revanche, est une colonne String de premier niveau comportant un index de saut bloom_filter dans le schéma d'otel_logs_v2 ; le contrôle préalable par granule élimine donc environ 99,9 % des granules avant toute lecture des données.
Le ralentissement d'un facteur 200 ne vient donc pas de la lenteur de Map, mais du fait que l'optimisation par index de saut ne s'applique pas aux clés de Map.
Correction rapide : index de saut avec filtre de Bloom sur mapValues
ALTER TABLE otel_logs_v2 ADD INDEX idx_request_id
mapValues(LogAttributes)
TYPE bloom_filter(0.01)
GRANULARITY 4;
ALTER TABLE otel_logs_v2 MATERIALIZE INDEX idx_request_id;
SELECT *
FROM otel_logs_v2
WHERE indexHint(has(mapValues(LogAttributes), 'abc123'))
AND LogAttributes['request_id'] = 'abc123';Cette opération construit un filtre de Bloom de toutes les valeurs de Map pour chaque granule. L'indication compatible has(mapValues(...)) permet à l'index d'éliminer les candidats, tandis que le prédicat par clé garantit toujours l'exactitude au niveau des lignes. Compromis : l'index couvre toutes les valeurs de Map ; les collisions sont donc plus nombreuses qu'avec un filtre de Bloom dédié sur une colonne promue. Mesurez le résultat avec EXPLAIN indexes = 1 ; la réussite du DDL ne prouve pas à elle seule que l'élimination est utile.
Correction durable : promouvoir request_id en colonne matérialisée
ALTER TABLE otel_logs_v2 ADD COLUMN request_id String MATERIALIZED LogAttributes['request_id'];
ALTER TABLE otel_logs_v2 ADD INDEX idx_request_id request_id TYPE bloom_filter(0.01) GRANULARITY 4;
ALTER TABLE otel_logs_v2 MATERIALIZE COLUMN request_id, INDEX idx_request_id;request_id est désormais une colonne de premier niveau qui possède sa propre compression et son propre filtre de Bloom. Requête : WHERE request_id = 'abc123' au lieu de WHERE LogAttributes['request_id'] = 'abc123'. Compromis : chaque promotion nécessite une réécriture de colonne (un passage MATERIALIZE ponctuel). Ce coût se justifie pour les clés fréquentes, pas pour celles de la longue traîne de LogAttributes.
Il s'agit précisément du motif d'évolution de schéma de la décision 3 de l'ADR de la partie 2 : Map par défaut, promotion des clés fréquentes.
Critères de décision
Les questions connexes du QCM valorisent un diagnostic qui :
- établit que le problème est l'« absence de parcours par index de saut lors du déréférencement de Map », et non la « lenteur de ClickHouse » ;
- cite le filtre de Bloom sur les valeurs de Map, assorti d'un prédicat compatible ou d'une indication d'index, comme correction rapide à mesurer ;
- cite la promotion en colonne comme correction durable ;
- reconnaît le compromis propre à chaque solution (index de Map : davantage de collisions ; promotion : coût d'ALTER).
Scénario 5 — analyse des compromis (conceptions d'alertes)
Tableau comparatif — corrigé type
| Propriété | Conception A (au moment de la requête) | Conception B (MV préagrégée) |
|---|---|---|
| Coût de lecture par évaluation | Élevé : toutes les 60 s, ClickHouse analyse 5 minutes de lignes brutes. À 1 million d'événements/s × 300 s, cela représente 300 millions de lignes analysées par évaluation. | Faible : la MV produit environ 1 ligne/minute par service. La requête sur 5 minutes lit environ 5 lignes. Réponse en quelques microsecondes. |
| Coût d'écriture par ligne ingérée | Nul : aucun traitement par ligne | Faible, mais non nul : chaque insertion déclenche la mise à jour de l'agrégation par compartiment de la MV. Le coût est borné par le nombre de compartiments, et non par le nombre de lignes. En pratique, la surcharge reste inférieure à 5 %. |
| Retard de mise à jour | Environ 60 s (intervalle d'interrogation) + latence de la requête | Environ 60 s (intervalle d'interrogation) ; la MV elle-même est mise à jour de façon synchrone à chaque insertion |
| Mise à l'échelle de la cardinalité (100 services × 50 points de terminaison) | Même coût d'analyse, quelle que soit la cardinalité (analyse la table brute) | Nombre de lignes de la MV = 5000 groupes service-point de terminaison × 1/min = 7,2 millions de lignes/jour. Toujours infime par rapport aux événements bruts ; aucun problème de mise à l'échelle |
Recommandation à 1 million d'événements/s — la conception B l'emporte
Le seuil de rentabilité entre A et B est atteint lorsque le coût de l'analyse de la table brute dépasse le coût de mise à jour de la MV par ligne. À 1 million d'événements/s :
- La conception A analyse 300 millions de lignes par évaluation. Même à 1 Go/s par processeur avec un cache froid, chaque requête se mesure en secondes, toutes les 60 secondes, toute la journée. Sur une semaine, cela représente des millions de secondes processeur exclusivement consacrées aux alertes.
- La conception B amortit la même agrégation dans le parcours d'insertion, où le coût n'est payé qu'une fois par ligne au lieu d'être repayé toutes les minutes. L'agrégation à l'insertion bénéficie également du traitement colonnaire par lots ; la mise à jour de l'état de chaque compartiment est presque gratuite avec le débit SIMD moderne.
La bonne intuition : les alertes qui analysent à nouveau les données brutes suivent le motif des transformations Elasticsearch. Les alertes fondées sur des MV préagrégées suivent le motif natif de ClickHouse. Avec le volume, cette dernière approche passe du confort à la nécessité autour de 100 000 événements/s ; à 1 million d'événements/s, la conception A consommerait davantage de processeur que la charge de travail qu'elle est censée surveiller.
Remarque : situations où la conception A reste pertinente
- Environnements à faible volume (moins de 10 000 événements/s), où le coût de l'évaluation est négligeable
- Alertes ponctuelles ou temporaires, pour lesquelles vous ne souhaitez pas provisionner de MV
- Alertes dont la forme de requête change chaque semaine (le schéma de la MV est fixe, tandis que les requêtes ponctuelles sont souples)
Critères de décision
Les questions connexes du QCM valorisent un raisonnement qui :
- établit correctement que le coût de lecture de la conception B est O(compartiments), tandis que celui de la conception A est O(événements bruts analysés) ;
- reconnaît la symétrie du compromis : A ne paie rien à l'écriture, mais beaucoup à la lecture ; B paie un peu à l'écriture et presque rien à la lecture ;
- choisit la conception B à 1 million d'événements/s et l'explique par l'amortissement (pas simplement par « les MV sont plus rapides ») ;
- obtient des points supplémentaires en signalant qu'il s'agit du motif d'agrégation à l'insertion ou au moment de la requête, le même qu'illustre l'AggregatingMergeTree
logs_summary_1minde la partie 3.
Révision du score appliqué
L'évaluation notée exige 16 réponses correctes sur 20 dans la partie appliquée. Si votre score est inférieur à ce seuil, utilisez les critères de décision ci-dessus pour repérer le scénario à revoir. Les lacunes les plus fréquentes sont les suivantes :
- Exercice 1 : traiter ClickHouse comme Elasticsearch (stocker une colonne par attribut, partitionner par event_type, placer l'horodatage en premier dans l'ordre). Relisez schema.sql et la fiche de la partie 2.
- Exercice 2 : oublier le retour arrière ou la réponse concernant la conformité. Le fil conducteur de l'atelier souligne à plusieurs reprises que la migration reste réversible jusqu'à la désactivation ; c'est la propriété à retenir.
- Exercice 4 : supposer que les types Map sont intrinsèquement lents. Ce n'est pas le cas : la question porte uniquement sur les optimisations applicables.
Revenez à la partie 4 et recommencez la partie appliquée après avoir revu le scénario manqué.