Stockage ClickHouse
ClickHouse est une base de données en colonnes conçue pour les charges de travail analytiques. Le package @mastra/clickhouse fournit des adaptateurs de stockage pour plusieurs domaines de stockage Mastra et constitue le backend recommandé pour l’observabilité en production.
ClickHouse est le plus souvent utilisé comme backend d’observabilité dédié dans une configuration de stockage composite, une autre base de données prenant en charge les domaines restants.
Quand utiliser ClickHouseLien direct vers Quand utiliser ClickHouse
Observabilité en production pour les traces, les journaux, les métriques, les scores et les commentaires.
Pour le développement local, utilisez un magasin composite qui combine LibSQL (pour la mémoire et les Workflows) et @mastra/duckdb (pour l’observabilité). Aucun ne couvre seul une configuration de développement : LibSQL n’implémente pas le domaine d’observabilité et DuckDB n’implémente pas les autres domaines. Consultez la présentation de l’observabilité pour un exemple.
InstallationLien direct vers Installation
- npm
- pnpm
- Yarn
- Bun
npm install @mastra/clickhouse@latest
pnpm add @mastra/clickhouse@latest
yarn add @mastra/clickhouse@latest
bun add @mastra/clickhouse@latest
Vous aurez également besoin d’un serveur ClickHouse en cours d’exécution. Consultez les options d’hébergement pour les choix gérés et auto-hébergés.
UtilisationLien direct vers Utilisation
Observabilité avec vNext (recommandé)Lien direct vers Observabilité avec vNext (recommandé)
ObservabilityStorageClickhouseVNext est l’implémentation actuelle du domaine d’observabilité. Elle utilise un schéma d’insertion seule soutenu par ReplacingMergeTree et est optimisée pour le volume généré par les traces, les journaux, les métriques, les scores et les commentaires.
Composez-la avec un autre adaptateur de stockage afin que les écritures d’observabilité ne concurrencent pas les données de votre application :
import { Mastra } from '@mastra/core'
import { MastraCompositeStore } from '@mastra/core/storage'
import { PostgresStore } from '@mastra/pg'
import { ObservabilityStorageClickhouseVNext } from '@mastra/clickhouse'
import { Observability, MastraStorageExporter } from '@mastra/observability'
const observabilityStore = new ObservabilityStorageClickhouseVNext({
url: process.env.CLICKHOUSE_URL!,
username: process.env.CLICKHOUSE_USERNAME!,
password: process.env.CLICKHOUSE_PASSWORD!,
})
export const mastra = new Mastra({
storage: new MastraCompositeStore({
id: 'composite-storage',
default: new PostgresStore({
id: 'pg',
connectionString: process.env.DATABASE_URL!,
}),
domains: {
observability: observabilityStore,
},
}),
observability: new Observability({
configs: {
default: {
serviceName: 'mastra',
exporters: [new MastraStorageExporter()],
},
},
}),
})
MastraStorageExporter sélectionne automatiquement la stratégie insert-only lorsque ClickHouse est le backend d’observabilité, ce qui offre le débit d’écriture le plus élevé. Consultez les stratégies de traçage pour plus de détails.
Observabilité avec le domaine héritéLien direct vers Observabilité avec le domaine hérité
ObservabilityStorageClickhouse est l’adaptateur d’observabilité d’origine et reste pris en charge pour les projets qui n’ont pas migré vers le schéma vNext. La forme de la configuration est identique à celle de la classe vNext.
import { ObservabilityStorageClickhouse } from '@mastra/clickhouse'
const observabilityStore = new ObservabilityStorageClickhouse({
url: process.env.CLICKHOUSE_URL!,
username: process.env.CLICKHOUSE_USERNAME!,
password: process.env.CLICKHOUSE_PASSWORD!,
})
Les nouveaux projets doivent plutôt utiliser ObservabilityStorageClickhouseVNext.
Migration du domaine hérité vers vNextLien direct vers Migration du domaine hérité vers vNext
Pour migrer les spans historiques de la table héritée mastra_ai_spans vers le schéma vNext, exécutez :
- npm
- pnpm
- Yarn
- Bun
npx mastra migrate
pnpm dlx mastra migrate
yarn dlx mastra migrate
bun x mastra migrate
La migration copie les données de spans de mastra_ai_spans dans mastra_span_events par lots d’une journée. Elle gère le mappage des colonnes et déduplique les lignes héritées. La table d’origine reste disponible comme sauvegarde. Après la migration, les traces apparaissent dans Studio via l’adaptateur vNext.
La table héritée n’est pas supprimée. Supprimez-la manuellement après avoir vérifié la migration.
ClickHouse pour chaque domaineLien direct vers ClickHouse pour chaque domaine
ClickhouseStoreVNext prend en charge les domaines memory, workflows et observability avec ClickHouse et utilise automatiquement l’adaptateur d’observabilité vNext. Utilisez-le lorsque vous souhaitez que ClickHouse prenne en charge l’ensemble de l’application sans configurer manuellement un magasin composite.
import { Mastra } from '@mastra/core'
import { ClickhouseStoreVNext } from '@mastra/clickhouse'
export const mastra = new Mastra({
storage: new ClickhouseStoreVNext({
id: 'clickhouse-storage',
url: process.env.CLICKHOUSE_URL!,
username: process.env.CLICKHOUSE_USERNAME!,
password: process.env.CLICKHOUSE_PASSWORD!,
}),
})
ClickhouseStoreVNext accepte la même configuration que ClickhouseStore et réutilise le même client ClickHouse dans tous les domaines.
Composition manuelleLien direct vers Composition manuelle
ClickhouseStore est la classe historique qui prend en charge tous les domaines avec l’adaptateur d’observabilité hérité. Les nouveaux projets doivent privilégier ClickhouseStoreVNext. Si vous devez personnaliser le composite (par exemple, pour remplacer un domaine par un autre backend), construisez-le manuellement :
import { Mastra } from '@mastra/core'
import { MastraCompositeStore } from '@mastra/core/storage'
import { ClickhouseStore, ObservabilityStorageClickhouseVNext } from '@mastra/clickhouse'
const credentials = {
url: process.env.CLICKHOUSE_URL!,
username: process.env.CLICKHOUSE_USERNAME!,
password: process.env.CLICKHOUSE_PASSWORD!,
}
export const mastra = new Mastra({
storage: new MastraCompositeStore({
id: 'composite-storage',
default: new ClickhouseStore({ id: 'clickhouse-storage', ...credentials }),
domains: {
observability: new ObservabilityStorageClickhouseVNext(credentials),
},
}),
})
Utiliser votre propre client ClickHouseLien direct vers Utiliser votre propre client ClickHouse
Transmettez un client préconfiguré lorsque vous avez besoin de paramètres de connexion personnalisés, tels que des délais d’expiration de requêtes, la compression ou des intercepteurs :
import { createClient } from '@clickhouse/client'
import { ClickhouseStore } from '@mastra/clickhouse'
const client = createClient({
url: process.env.CLICKHOUSE_URL!,
username: process.env.CLICKHOUSE_USERNAME!,
password: process.env.CLICKHOUSE_PASSWORD!,
request_timeout: 60_000,
compression: { request: true, response: true },
})
const storage = new ClickhouseStore({ id: 'clickhouse-storage', client })
La même forme de client est acceptée par ObservabilityStorageClickhouse et ObservabilityStorageClickhouseVNext.
ConfigurationLien direct vers Configuration
Options de ClickhouseStoreLien direct vers clickhousestore-options
id:
url?:
https://your-instance.clickhouse.cloud:8443 ou http://localhost:8123). Obligatoire lorsque vous ne transmettez pas de client préconfiguré.username?:
client préconfiguré.password?:
client préconfiguré. Il peut s’agir d’une chaîne vide pour l’utilisateur par défaut sur une instance locale.client?:
@clickhouse/client. Utilisez-le lorsque vous avez besoin de paramètres de requête personnalisés. S’exclut mutuellement avec les champs d’identification ci-dessus.ttl?:
NANOSECOND à YEAR.replication?:
cluster est défini, Mastra ajoute également ON CLUSTER au langage de définition de données (DDL) détenu par Mastra.disableInit?:
true, le magasin n’exécute pas la création de tables ni les migrations à la première utilisation. Appelez explicitement storage.init() depuis vos scripts de déploiement.ClickhouseStore accepte également toutes les options de ClickHouseClientConfigOptions (telles que database, request_timeout, compression, keep_alive et max_open_connections).
Clusters répliquésLien direct vers Clusters répliqués
Utilisez replication lorsque Mastra écrit dans un cluster ClickHouse à plusieurs répliques via un équilibreur de charge.
const storage = new ClickhouseStoreVNext({
id: 'clickhouse-storage',
url: process.env.CLICKHOUSE_URL!,
username: process.env.CLICKHOUSE_USERNAME!,
password: process.env.CLICKHOUSE_PASSWORD!,
replication: {
cluster: 'company_cluster',
},
})
Lorsque replication est défini, Mastra réécrit ses moteurs de table MergeTree et ReplacingMergeTree en ReplicatedMergeTree et ReplicatedReplacingMergeTree. Les arguments de moteur par défaut sont :
zookeeperPath:'/clickhouse/tables/{shard}/{database}/{table}'replicaName:'{replica}'
Les valeurs par défaut correspondent à la convention auto-gérée la plus courante. Si les tables existantes de votre cluster utilisent une disposition différente (par exemple, /clickhouse/tables/{shard}/{table} sans le segment {database}), définissez explicitement zookeeperPath pour la reproduire. Mastra ne lit pas la convention de votre cluster depuis Keeper ; une valeur par défaut non correspondante écrit donc les métadonnées Mastra dans une branche distincte du reste du cluster.
new ClickhouseStoreVNext({
url: process.env.CLICKHOUSE_URL!,
username: process.env.CLICKHOUSE_USERNAME!,
password: process.env.CLICKHOUSE_PASSWORD!,
replication: {
cluster: 'company_cluster',
zookeeperPath: '/clickhouse/tables/{shard}/{table}',
},
})
Définissez cluster pour ajouter ON CLUSTER aux DDL détenus par Mastra, tels que la création de tables, la création de vues matérialisées, les migrations de colonnes, les modifications de TTL et les suppressions de tables.
Les opérations de maintenance manuelle telles que optimizeTable() et materializeTtl() s’exécutent sur chaque réplique lorsque cluster est défini. Ces opérations peuvent être coûteuses sur un grand cluster. Préférez les exécuter en dehors des heures de pointe et laissez les fusions de routine se produire dans la file de fusion d’arrière-plan plutôt que de les déclencher à chaque redémarrage.
Si des tables Mastra existantes utilisent les moteurs locaux MergeTree ou ReplacingMergeTree, l’initialisation échoue tant que replication est activé. Mastra refuse de convertir silencieusement les tables locales, car la copie et le remplacement ne sont pas sûrs entre les répliques. Pour migrer, recréez les tables concernées en Replicated* avant d’activer la réplication. Pour migrer en toute sécurité, renommez la table locale, exécutez CREATE TABLE ... ENGINE = ReplicatedMergeTree(...) ON CLUSTER ..., exécutez INSERT INTO ... SELECT * FROM <renamed_local>, puis supprimez <renamed_local>.
Ne définissez pas replication sur ClickHouse Cloud. Cloud réécrit MergeTree en SharedMergeTree côté serveur, et des moteurs ReplicatedMergeTree explicites produisent des DDL incorrects. replication est réservé aux clusters auto-gérés à plusieurs répliques.
Options du domaine d’observabilitéLien direct vers Options du domaine d’observabilité
ObservabilityStorageClickhouse et ObservabilityStorageClickhouseVNext acceptent les mêmes options de connexion que ClickhouseStore (url, username, password ou un client préconfiguré).
Options d’hébergementLien direct vers Options d’hébergement
ClickHouse s’exécute partout où vous pouvez y accéder via HTTP. Les choix courants incluent :
- ClickHouse Cloud : service géré avec une offre d’essai gratuite. Fournit des informations de connexion directement compatibles avec
url,usernameetpassword. - Auto-hébergé : exécutez le conteneur officiel
clickhouse/clickhouse-serverou installez ClickHouse depuis les packages officiels. Convient aux VPS, au matériel dédié ou à Kubernetes.
Pour le développement local :
docker run -d --name mastra-clickhouse \
-p 8123:8123 -p 9000:9000 \
-e CLICKHOUSE_USER=default \
-e CLICKHOUSE_PASSWORD=password \
clickhouse/clickhouse-server
new ObservabilityStorageClickhouseVNext({
url: 'http://localhost:8123',
username: 'default',
password: 'password',
})
Déploiement avec Railway et des plateformes similairesLien direct vers Déploiement avec Railway et des plateformes similaires
Les plateformes comme Railway, Fly.io, Render et Heroku exécutent des conteneurs d’application sur des systèmes de fichiers éphémères. Les backends d’observabilité intégrés tels que DuckDB nécessitent un fichier local persistant et accessible en écriture ; ils perdent donc leurs données au redémarrage ou échouent entièrement à se déployer sur ces plateformes.
Utilisez plutôt ClickHouse. Comme ClickHouse est accessible via HTTP, la même connexion fonctionne depuis n’importe quel hôte :
import { Mastra } from '@mastra/core'
import { MastraCompositeStore } from '@mastra/core/storage'
import { PostgresStore } from '@mastra/pg'
import { ObservabilityStorageClickhouseVNext } from '@mastra/clickhouse'
import { Observability, MastraStorageExporter } from '@mastra/observability'
export const mastra = new Mastra({
storage: new MastraCompositeStore({
id: 'composite-storage',
default: new PostgresStore({
id: 'pg',
connectionString: process.env.DATABASE_URL!,
}),
domains: {
observability: new ObservabilityStorageClickhouseVNext({
url: process.env.CLICKHOUSE_URL!,
username: process.env.CLICKHOUSE_USERNAME!,
password: process.env.CLICKHOUSE_PASSWORD!,
}),
},
}),
observability: new Observability({
configs: {
default: {
serviceName: 'mastra',
exporters: [new MastraStorageExporter()],
},
},
}),
})
Provisionnez la base de données avec l’une des options suivantes :
- Géré : utilisez ClickHouse Cloud. Définissez
CLICKHOUSE_URL,CLICKHOUSE_USERNAMEetCLICKHOUSE_PASSWORDcomme variables d’environnement sur votre plateforme d’hébergement. - Auto-hébergé sur Railway : ajoutez un service ClickHouse à votre projet Railway à partir de l’image Docker officielle, puis référencez-le dans le service d’application via le réseau privé de Railway.
La même approche s’applique aux autres hôtes dotés de systèmes de fichiers éphémères. Pour les données d’application qui doivent également être stockées hors hôte, associez cette configuration à une instance PostgreSQL gérée ou LibSQL/Turso pour le stockage default.
Ne faites pas pointer un backend intégré tel que DuckDB vers un chemin situé dans un système de fichiers de conteneur éphémère. Les données qui y sont écrites sont perdues au redémarrage du conteneur et, sur certaines plateformes, le chemin est en lecture seule.
InitialisationLien direct vers Initialisation
Lorsqu’il est transmis à la classe Mastra, ClickhouseStore appelle automatiquement init() afin de créer le schéma et d’exécuter les migrations en attente. Il en va de même pour ObservabilityStorageClickhouseVNext lorsqu’il est utilisé via MastraCompositeStore.
Si vous gérez le stockage en dehors de Mastra, appelez explicitement init() :
import { ObservabilityStorageClickhouseVNext } from '@mastra/clickhouse'
const observability = new ObservabilityStorageClickhouseVNext({
url: process.env.CLICKHOUSE_URL!,
username: process.env.CLICKHOUSE_USERNAME!,
password: process.env.CLICKHOUSE_PASSWORD!,
})
await observability.init()
Dans les pipelines CI/CD, définissez disableInit: true sur ClickhouseStore et exécutez init() depuis une étape de déploiement qui utilise des informations d’identification élevées. Les informations d’identification de l’application à l’exécution peuvent alors être limitées à la lecture et à l’insertion.
ObservabilitéLien direct vers Observabilité
ClickHouse est le backend recommandé pour l’observabilité en production :
- Stratégie d’insertion seule :
MastraStorageExporterécrit les spans terminés par lots sans mises à jour par span ; c’est la stratégie disponible au débit le plus élevé. - Compression en colonnes : les attributs de spans et les charges utiles de journaux se compressent bien par rapport aux mêmes données dans des bases de données orientées lignes.
Pour la matrice complète des stratégies et les conseils de production, consultez la référence de MastraStorageExporter.