Architecture de Stockage et Concepts Fondamentaux
ClickHouse est spécifiquement conçu pour les scénarios d'écriture par lots massifs et à faible fréquence. Il ne doit pas être utilisé comme une file d'attente de messages. La règle d'or pour garantir la stabilité du système est de minimiser la fréquence des écritures tout en maximisant la taille des lots.
Physiquement, les données sont organisées dans une arborescence de répertoires. Par exemple, le chemin /var/lib/clickhouse/data/analytics_db/sensor_metrics/ contient les dossiers parts. Chaque insertion génère un nouveau part. Les parts appartenant à la même partition logique seront automatiquement fusionnés en arrière-plan. Il est crucial de noter que la partition est un concept purement logique ; il n'existe pas de répertoire physique dédié aux partitions sur le disque.
Comprendre les Goulots d'Étranglement des E/S
Pour comprendre pourquoi ClickHouse excelle là où les bases de données relationnelles traditionnelles (OLTP) peinent sur de gros volumes, il faut analyser les limites des disques durs mécaniques (HDD). Un disque classique de 7200 RPM offre environ 100 IOPS (opérations d'entrée/sortie par seconde). Cela signifie qu'il ne peut effectuer que 100 lectures aléatoires par seconde.
Si une requête nécessite la lecture aléatoire de milliers de lignes dispersées sur le disque, le temps de réponse explose à cause du temps de recherche (seek time) et de la latence de rotation. À l'inverse, ClickHouse contourne ce problème en privilégiant les E/S séquentielles. Lors d'une analyse de table, les données sont lues de manière contiguë, permettant d'atteindre des débits de 100 à 200 Mo/s, saturant ainsi la bande passante du disque plutôt que son IOPS.
Déploiement et Configuration sur Ubuntu
Voici la procédure standard pour installer ClickHouse sur un système basé sur Debian/Ubuntu en utilisant le dépôt officiel.
1. Configuration du dépôt et installation
# Installation des dépendances requises
sudo apt-get install -y apt-transport-https ca-certificates curl gnupg
# Ajout de la clé GPG officielle
curl -fsSL 'https://packages.clickhouse.com/rpm/lts/repomd.xml.key' | sudo gpg --dearmor -o /usr/share/keyrings/clickhouse-keyring.gpg
# Configuration du dépôt APT
ARCH=$(dpkg --print-architecture)
echo "deb [signed-by=/usr/share/keyrings/clickhouse-keyring.gpg arch=${ARCH}] https://packages.clickhouse.com/deb stable main" | sudo tee /etc/apt/sources.list.d/clickhouse.list
# Mise à jour et installation
sudo apt-get update
sudo apt-get install -y clickhouse-server clickhouse-client
Note : Lors de l'installation, le système vous demandera de définir un mot de passe pour l'utilisateur par défaut.
2. Configuration réseau et stockage
Éditez le fichier /etc/clickhouse-server/config.xml pour autoriser les connexions externes et personnaliser le répertoire de données :
<!-- Autoriser les écouteurs sur toutes les interfaces -->
<listen_host>0.0.0.0</listen_host>
<!-- Redéfinir le chemin des données (optionnel) -->
<path>/opt/clickhouse/data/</path>
Si vous modifiez le chemin des données, assurez-vous d'appliquer les droits corrects :
sudo chown -R clickhouse:clickhouse /opt/clickhouse/data/
3. Démarrage et connexion
# Démarrage du service
sudo systemctl start clickhouse-server
sudo systemctl enable clickhouse-server
# Connexion via le client
clickhouse-client --password
Protocoles de Connectivité
ClickHouse expose deux interfaces réseau principales :
- TCP (Port 9000) : Protocole natif, offrant les meilleures performances. Il est utilisé pour la communication interne entre les nœuds du cluster et par l'interface en ligne de commande (CLI).
- HTTP (Port 8123) : Protocole RESTful, offrant une compatibilité universelle. Idéal pour les intégrations avec des langages comme Python, Go ou via des requêtes
curl.
Pour les applications Java, il est recommandé d'utiliser le pilote natif (clickhouse-client) plutôt que le pilote JDBC (clickhouse-jdbc) si les performances brutes sont critiques, car le JDBC ajoute une couche d'abstraction.
Indexation Secondaire et Filtres de Bloom
ClickHouse utilise des index secondaires de type "Skip Index" (index de saut). Le type ngrambf_v1 est un filtre de Bloom basé sur des N-grammes, extrêmement efficace pour les recherches de chaînes de caractères.
Pourquoi un filtre de Bloom est-il si compact ?
Contrairement à un index B-Tree, un filtre de Bloom ne stocke pas les données elles-mêmes, mais uniquement leurs empreintes numériques (hash). Il s'agit d'un tableau de bits de taille fixe.
Prenons l'exemple d'un Granule (bloc de données) contenant des milliers de lignes. Chaque chaîne de caractères est décomposée en N-grammes. Chaque N-gramme est passé à travers plusieurs fonctions de hash, et les bits correspondants dans le tableau sont mis à 1.
- Taille fixe : Que le bloc contienne 100 ou 100 000 N-grammes, la taille du tableau de bits (par exemple, 4096 bits = 512 octets) ne change pas.
- Compression par collision : Différents N-grammes peuvent activer le même bit. Cela crée un taux de faux positifs, mais garantit qu'aucun vrai positif n'est manqué (pas de faux négatifs).
Cette structure permet de pré-filtrer les blocs de données en mémoire avec une empreinte disque négligeable, accélérant drastiquement les requêtes de type LIKE ou MULTI_SEARCH.
Analyse et Optimisation des Requêtes
Pour déboguer et optimiser les requêtes, ClickHouse fournit plusieurs outils d'inspection.
Utilisation de EXPLAIN
-- Afficher le plan logique (arbre de syntaxe)
EXPLAIN SYNTAX SELECT * FROM analytics.web_traffic WHERE region = 'EU';
-- Afficher le plan physique (pipeline d'exécution)
EXPLAIN PIPELINE SELECT * FROM analytics.web_traffic WHERE region = 'EU';
-- Estimer les statistiques (lignes et octets à lire)
EXPLAIN ESTIMATE SELECT * FROM analytics.web_traffic WHERE event_date >= '2024-01-01';
Analyse des journaux de trace
Pour une analyse granulaire, activez le niveau de log trace directement dans la requête :
SELECT count()
FROM analytics.web_traffic
WHERE event_date = '2024-05-15'
SETTINGS send_logs_level = 'trace';
Cela affichera dans la console les détails de l'exécution, notamment l'application des index pirmaires, le filtrage des marques (marks), et le nombre de blocs (granules) lus par rapport au total.
Sémantique SQL et Clauses d'Agrégation
HAVING vs WHERE (Poussée de prédicats)
La clause HAVING filtre les résultats après l'agrégation, tandis que WHERE filtre avant.
-- Moins optimal : agrège toutes les données, puis filtre
SELECT region, COUNT() AS total_hits
FROM analytics.web_traffic
GROUP BY region
HAVING total_hits > 10000;
-- Plus optimal : filtre avant l'agrégation (Predicate Pushdown)
SELECT region, COUNT() AS total_hits
FROM (
SELECT region
FROM analytics.web_traffic
WHERE status_code = 200
)
GROUP BY region;
Cependant, HAVING est indispensable lorsque le filtre doit s'appliquer sur une valeur agrégée calculée, comme une moyenne ou une somme.
DISTINCT vs GROUP BY
Bien que DISTINCT et GROUP BY puissent produire des résultats identiques pour une simple déduplication, leurs plans d'exécution diffèrent.
-- Utilisation de DISTINCT
SELECT DISTINCT user_id FROM analytics.user_sessions;
-- Équivalent avec GROUP BY
SELECT user_id FROM analytics.user_sessions GROUP BY user_id;
Le plan d'exécution de DISTINCT est généralement plus simple et peut bénéficier d'optimisations spécifiques, comme l'arrêt prématuré de la lecture si une clause LIMIT est présente sans ORDER BY.
Administration, Sauvegarde et Monitoring
Gestion des utilisateurs et sécurité
Les utilisateurs sont définis dans le fichier users.xml (ou dans le répertoire users.d/). Les mots de passe ne doivent jamais être stockés en clair. ClickHouse supporte SHA256 et Double SHA1.
Génération d'un hash SHA256 pour le mot de passe MySecurePass!2024 :
echo -n 'MySecurePass!2024' | openssl dgst -sha256
Intégration dans la configuration XML :
<users>
<analyst_user>
<password_sha256_hex>[HASH_GENERE_PRECEDemment]</password_sha256_hex>
<networks>
<ip>::/0</ip>
</networks>
<profile>default</profile>
</analyst_user>
</users>
Stratégies de Sauvegarde
ClickHouse offre plusieurs mécanismes pour la sauvegarde des données :
- Export/Import logique : Via le client CLI avec
FORMAT TSVouCSV. Utile pour de petits volumes ou l'export partiel. - FREEZE (Snapshot de partition) :
ALTER TABLE tb FREEZE PARTITION '2024-05'. Cette commande crée des liens physiques (hardlinks) des fichiers de données dans le répertoireshadow/. Cela ne consomme pas d'espace disque supplémentaire instantanément et permet une sauvegarde à chaud. - FETCH (Restauration depuis réplica) :
ALTER TABLE tb FETCH PARTITION '2024-05' FROM '/clickhouse/tables/node01/tb'. Télécharge les données directement depuis ZooKeeper ou un autre réplica.
Attention : Ni FREEZE ni FETCH ne sauvegardent les métadonnées (fichiers .sql dans le dossier metadata/). Elles doivent être sauvegardées séparément.
Monitoring via les Tables Système
ClickHouse expose son état interne via des tables système optimisées en lecture seule.
Indicateurs en temps réel
-- Métriques instantanées (requêtes en cours, fusions actives)
SELECT metric, value, description FROM system.metrics LIMIT 10;
-- Métriques asynchrones (mémoire allouée, files d'attente des réplicas)
SELECT metric, value FROM system.asynchronous_metrics WHERE metric LIKE '%Memory%' OR metric LIKE '%Queue%';
Historique des événements et requêtes
Pour une analyse post-mortem, activez et interrogez les tables de logs :
-- Analyse des requêtes les plus coûteuses en mémoire
SELECT
query,
formatReadableSize(memory_usage) AS mem_used,
read_rows,
event_time
FROM system.query_log
WHERE type = 'QueryFinish' AND event_time > now() - INTERVAL 1 HOUR
ORDER BY memory_usage DESC
LIMIT 5;
-- Cumul des événements système (lectures de fichiers, insertions)
SELECT event, value FROM system.events ORDER BY value DESC LIMIT 10;