Base de données d’événements horodatés orientée colonne
Ce type de base a pour ambition de permettre l’analyse des flots d’événements horodatés sur une période plus ou moins longue. À froid pour chercher et comprendre. À chaud (en continu) pour visualiser, surveiller et déclencher des actions.
Ce sont les “timeseries database”.
Prometheus a popularisé ce type d’outil devenu indispensable à l’age du Cloud.
Comme tant d’autres avant lui, Prometheus a fait le choix d’implémenter son langage de requête et son propre moteur de stockage qui gère très mal une grande diversité de labels (explosion d’arité) et sa compression est rudimentaire.
Les produits concurrents, pour pouvoir se concentrer sur la couche applicative, préfèrent s’appuyer sur des technologies adaptées, matures et éprouvées, comme les bases de données orientées colonnes.
Je vais maintenant vous présenter ces deux concepts : la base de données orientée colonnes, puis la “timeseries” et plus spécifiquement la télémétrie et l’observabilité des serveurs et applications.
Je casse le suspens tout de suite : la réponse est Clickhouse, mais ce sera dans le deuxième épisode.
Orienté colonnes
Lignes ou colonnes
Le monde se divise en deux catégories : les lignes et les colonnes
Les très répandues bases de données relationnelles (Mysql, Postgresql, Sqlite …) ont pour modèle de données la table composée de lignes, avec plusieurs colonnes. Ce modèle se concentre sur les liens entre différentes tables avec une garantie de cohérence. Les modifications sont atomiques, rapides et synchrones. La modification peut concerner une seule ligne, ou plusieurs (sur une ou plusieurs tables) regroupés dans une transaction.
Ce modèle est nommé OLTP (acronyme de online transaction processing) traduit par traitement transactionnel en ligne.
La gestion des tables à gros volume et gros débit d’insertion posent de sérieux problèmes : * la gestion des transactions légères ralentit le débit en écriture. * itérer sur une table nécessite de lire chacune des lignes, même si quelques colonnes nous intéressent. * la compression ne peut se faire que sur une valeur, suffisamment lourde (comme un énorme VARCHAR) pour être rentable. Impossible de passer à l’échelle du Big Data avec ces contraintes.
Il va falloir changer d’approche pour pouvoir manipuler de grandes quantités de données. Une approche avec des forces et faiblesses opposées à celle du modèle orienté ligne : le modèle orienté colonnes.
Ces deux modèles partagent des caractéristiques, comme le modèle basé sur la table avec des valeurs typées et la possibilité d’utiliser du SQL. La différence fondamentale est qu’une table est composée de lignes (avec des colonnes) pour l’une, des colonnes (avec des lignes) pour l’autre.
Colonnes
Les colonnes sont de longues listes de valeurs typées et contiguës, permettant une compression efficace et des lectures/écritures bien séquentielles. Le stockage, que ce soit sur un disque dur, un SSD ou même du S3, est bien plus performant avec des données regroupées en larges blocs. Ces longues colonnes de données permettent de paralléliser leur traitement avec les instructions SIMD du processeur. Meilleure compression, débit et temps de traitement, trois points forts indispensables pour manipuler de grandes quantités de données. Qui dit points forts dit aussi points faibles, tout a un prix.
Ajouter, modifier, effacer
Les bases de données orientées colonnes sont conçues pour pouvoir ingérer d’énormes flots de données.
Pour avoir des performances maximales, une spécialisation radicale et monomaniaque est nécessaire, au détriment d’autres fonctionnalités. En partant du principe que les données sont uniquement ajoutées, jamais modifiées, l’implémentation se simplifie drastiquement. Il suffit de n’autoriser que les ajouts des données à un fichier existant (et en créer de nouveau). Simple, robuste, performant. Optimisation ultime, mais pénible à l’usage. Il est possible d’ajouter au concept d‘“append only” une surcouche permettant de modifier ou effacer des données. Ces modifications ont comme priorité n°1 de ne surtout pas pénaliser le débit en écriture/lecture de la base de données. La modification en elle-même a une bien moindre priorité et des concessions (comme le risque de doublon, l’écriture asynchrone, l’impossibilité de regrouper plusieurs modifications dans une transaction…). Chaque base aura ses propres spécificités pour pouvoir modifier ses données, avec des performances moindres.
Effectuer des modifications par lot permet de créer directement de longues colonnes favorisant la compression. En simplifiant, ce lot sera validé (type, contraintes), chiffré, compressé pour former un bloc (une tranche de table) qui sera persisté. Pour avoir une idée de l’échelle, un lot devrait contenir au moins un millier de lignes pour avoir de belles performances. La base acceptera les insertions une à une, la taille du lot n’est qu’une recommandation, mais les performances seront désastreuses. Certaines bases seront capables de compromis en ajoutant les modifications dans un tampon, puis d’en faire un lot.
C’est bien d’être capable d’engloutir des millions de lignes, mais il faut ensuite pouvoir les lire. Une requête va devoir, en théorie, lire l’intégralité d’une table pour construire sa réponse. Première optimisation des tables orientées colonnes : seules les colonnes réclamées dans la requête seront lues.
Sur une table triée par une ou plusieurs colonnes, l’itération des valeurs pourra être interrompue si on sait que les valeurs suivantes ne pourront plus être sélectionnées par le filtre. Ce sera tout de suite plus clair avec un exemple : avec une table triée par sa colonne “date”, le filtre “moins de 7 jours” stoppera la lecture dès que la valeur dans la colonne date sera supérieure à 7 jours. Une table triée avec une clef compatible avec celle de la requête pourra envoyer sa réponse directement, sans devoir la trier de nouveau. Choisir judicieusement la clef de tri de sa table permet d’accélérer un type de requête, a priori la plus utilisée. Il peut y avoir plusieurs types de requêtes qui ont besoin de performance, mais la table n’a qu’une seule clef de tri. Le modèle orienté colonnes a pour ça le concept de la projection. Chaque projection d’une table est écrite en utilisant ses propres clefs de tri. Le débit d’écriture sera impacté, mais c’est surtout le volume de stockage qui va être multiplié. La projection ne doit être envisagée qu’après les autres optimisations disponibles.
Toutes les bases orientées colonnes découpent leurs tables en tranches et les réécrivent, en tache de fond, pour appliquer les modifications et diverses optimisations. La règle de découpage peut être définie lors de la création de la table. Prenons de nouveau un exemple de données horodatées. Avec une table découpée par mois, une recherche sur la semaine courante n’aura besoin que de deux tranches (si la semaine est à cheval sur deux mois). Avec ce même découpage, si l’on souhaite ne conserver que 12 mois de données, il suffira d’effacer la première tranche dès que l’on crée la treizième.
Même ça ne fait pas partie de la définition canonique des tables orientées colonnes, la plupart des bases permettent d’annoter les tranches pour déterminer rapidement s’il est nécessaire de la lire pour traiter une requête. Le terme technique est skip-index. Annoter les valeurs minimale et maximale d’une colonne est un exemple simple.
Interroger les données
SQL
Le langage SQL est le standard pour interagir avec une base de données, qu’elle soit orientée lignes ou colonnes. Le SQL est un standard, même si chaque base utilise un dialecte subtilement différent, justifié par les différentes fonctionnalités qu’elles fournissent.
Cette universalité abaisse le ticket d’entrée pour les nouveaux utilisateurs. De plus, ce langage est commun entre différents métiers et l’interface utilisateur facilite sa prise en main. Le concept de SQL est de pouvoir exprimer un besoin métier, le moteur (et les experts) se chargeront des stratégies et optimisations possibles.
Toutes les analyses de données débuteront par une requête, décrite depuis une interface, écrite à la main ou générée par du code.
Une requête permet de créer des tableaux et des graphiques pour analyser des données qui serviront ensuite à composer un rapport ou un tableau de bord. Le terme technique est OLAP (OnLine Analytical Processing) soit “Traitement analytique en ligne” en bon français. OLAP est utilisé pour la BI (Business Intelligence), traduit en “informatique décisionnel”.
Le langage SQL permet de créer/modifier/effacer des données, mais c’est dans la sélection de données qu’il est le plus expressif. L’étape filtrer et grouper n’est pas compliquée à définir, pour les jointures, c’est un peu plus sportif. L’étape calcul et analyse utilise des fonctions, tout ce qu’il y a de plus classique. Le SQL perd rapidement sa lisibilité avec des requêtes complexes, il est difficile de réutiliser du code. La réponse officielle (et pragmatique) est d’utiliser des vues et de définir des fonctions (User Defined Function).
Implémenter un moteur SQL est tout sauf trivial. De plus, le SQL peut être perçu comme surdimensionné pour les besoins d’une base de données très spécialisée et qu’un DSL sera plus simple à utiliser (et implémenter).
Aide et assistance à la création de requête
Entre le SQL orthodoxe et le DSL lié à sa base de données, il existe une solution intermédiaire : utiliser un DSL générique qui sera traduit en SQL. Malloy et PRQL sont deux exemples qui ont un peu de visibilité. Bien que prometteurs, ils sont encore anecdotiques.
Les interfaces graphiques aident beaucoup à écrire des requêtes. Les “query builder” permettent de définir une requête en cliquant sur beaucoup de menus déroulants, sans trop se soucier du SQL. Les éditeurs riches, eux, aident à écrire du SQL en proposant de la complétion et une validation en direct de la syntaxe.
Les LLM sont capables de découvrir l’organisation de vos tables, créant ainsi le contexte pour décrire sa demande et finalement aboutir à une élégante requête SQL.
Base de données horodatées
Une base de données horodatées est spécialisée dans la gestion des événements horodatés, a priori immuable. Son petit nom est TSDB pour Time Series DataBase.
Ce genre de base de données peut gérer tout ce qui a un horodatage (capteurs physiques, valeurs en bourse…), mais là, je vais parler spécifiquement du monitoring en informatique.
Dans ce domaine, les événements sont regroupés en 3 catégories : * une mesure avec quelques étiquettes (nom de la mesure, de l’application, du serveur …) * des données plus ou moins structurées : une ligne de log, un rapport d’erreur… * Des événements distincts mais regroupés entre eux, comme la trace des services utilisés pour l’appel d’une URL (base de données, cache, autre service…)
La nomenclature utilisée par Opentelemetry parle de différents signaux : métrique, journal et trace, ce qui donne en anglais : signals, metric, log et trace.
Le flot d’événements peut être énorme et théoriquement infini. Pour maîtriser le volume de stockage, il faut une fréquence d’échantillonnage raisonnable pour les métriques, et globalement, pour tous les signaux, une politique d’éviction pour effacer (ou archiver) les données trop anciennes. Le droit à l’oubli.
Pour conserver une vision sur un temps long, sans saturer ses disques durs, il est possible de consolider les métriques sur une fréquence plus large. En passant d’une fréquence de 10s à 10 minutes en ne conservant que la valeur médiane, par exemple. La consolidation ne sera pas possible pour les journaux et les traces, mais l’échantillonnage est simple à mettre en place de manière naïve. Des règles métiers peuvent aussi être utilisées pour ne conserver que les données de valeurs. Pour des journaux systèmes, par exemple, passer du niveau INFO à ERROR devrait diminuer significativement le volume de données.
Les TSDB peuvent être requêtées sur des sujets spécifiques au monitoring. * corrélation entre des mesures et des événements apparaissant dans les journaux * analyse de performance et recherche de goulets d’étranglements * déclenchement d’une alerte ou directement une action de remédiation * aide à la résolution d’incidents * détection d’anomalies (régressions, attaque, prémisse d’un incident…) * planification des ressources nécessaires à une utilisation plus intense du service métier
Aller plus loin
Comme promis, Clickhouse sera décortiqué dans le prochain épisode. Conçu pour l’OLAP il se positionne comme challengeur de Prometheus et Elasticsearch (et d’à peu près tout le monde).
Quelles sont ses choix pour atteindre de telles performances ? Quelles sont ses stratégies pour faire sa place dans l’univers du monitoring ?
