跳至主要內容

ClickHouse 儲存空間

ClickHouse 是專為分析工作負載設計的欄式資料庫。@mastra/clickhouse 套件為多個 Mastra 儲存 domain 提供儲存 adapter,也是正式環境可觀測性的建議 backend。

ClickHouse 最常在複合儲存空間設定中作為專用可觀測性 backend,並由另一個資料庫處理其餘 domain。

適合使用 ClickHouse 的時機
「適合使用 ClickHouse 的時機」的直接連結

在正式環境中儲存 Trace、log、metric、分數與意見回饋等可觀測性資料。

進行本機開發時,請使用結合 LibSQL(用於記憶體與 Workflow)和 @mastra/duckdb(用於可觀測性)的複合 store。兩者單獨使用都無法涵蓋完整開發設定:LibSQL 未實作 observability domain,而 DuckDB 未實作其他 domain。範例請參閱可觀測性概觀。

安裝
「安裝」的直接連結

npm install @mastra/clickhouse@latest

你也需要一個執行中的 ClickHouse 伺服器。受管理與自行託管選項請參閱託管選項。

使用方式
「使用方式」的直接連結

ObservabilityStorageClickhouseVNext 是目前的 observability domain 實作。它使用以 ReplacingMergeTree 為基礎的 insert-only schema,並針對 Trace、log、metric、分數與意見回饋所產生的資料量進行最佳化。

將它與其他儲存 adapter 組合使用,避免可觀測性寫入與應用程式資料相互競爭:

src/mastra/index.ts
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()],
},
},
}),
})

當 ClickHouse 作為可觀測性 backend 時,MastraStorageExporter 會自動選擇 insert-only 策略,以提供最高寫入吞吐量。詳情請參閱 tracing strategy。

搭配舊版 domain 使用可觀測性
「搭配舊版 domain 使用可觀測性」的直接連結

ObservabilityStorageClickhouse 是原始可觀測性 adapter,尚未遷移至 vNext schema 的專案仍可使用。其設定結構與 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!,
})

新專案應改用 ObservabilityStorageClickhouseVNext。

從舊版遷移至 vNext
「從舊版遷移至 vNext」的直接連結

若要將歷史 span 從舊版 mastra_ai_spans 資料表遷移至 vNext schema,請執行:

npx mastra migrate

Migration 會以一天為單位,將 span 資料從 mastra_ai_spans 複製到 mastra_span_events。它會處理欄位對應,並將舊版資料列去重複。原始資料表會保留作為備份。遷移後,Trace 會透過 vNext adapter 顯示在 Studio 中。

備註

系統不會刪除舊版資料表。請在確認遷移結果後手動刪除。

為所有 domain 使用 ClickHouse
「為所有 domain 使用 ClickHouse」的直接連結

ClickhouseStoreVNext 使用 ClickHouse 支援 memory、workflows 與 observability domain,並自動採用 vNext 可觀測性 adapter。若希望整個應用程式都由 ClickHouse 支援,而不想手動連接複合 store,請使用此類別。

src/mastra/index.ts
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 接受與 ClickhouseStore 相同的設定,並在所有 domain 間重複使用同一個 ClickHouse client。

手動組合
「手動組合」的直接連結

ClickhouseStore 是長期使用的類別,透過舊版可觀測性 adapter 支援每個 domain。新專案應優先使用 ClickhouseStoreVNext。若需要自訂複合儲存空間(例如以不同 backend 覆寫某個 domain),請手動建立:

src/mastra/index.ts
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),
},
}),
})

使用自己的 ClickHouse client
「使用自己的 ClickHouse client」的直接連結

需要請求逾時、壓縮或 interceptor 等自訂連線設定時,請傳入預先設定的 client:

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 })

ObservabilityStorageClickhouse 與 ObservabilityStorageClickhouseVNext 也接受相同的 client 形式。

設定
「設定」的直接連結

ClickhouseStore 選項
「clickhousestore-options」的直接連結

id:

string
此儲存空間執行個體的唯一識別碼。

url?:

string
ClickHouse 伺服器 URL(例如 https://your-instance.clickhouse.cloud:8443 或 http://localhost:8123)。未傳入預先設定的 client 時為必填。

username?:

string
ClickHouse 使用者名稱。未傳入預先設定的 client 時為必填。

password?:

string
ClickHouse 密碼。未傳入預先設定的 client 時為必填。本機執行個體的預設使用者可以使用空字串。

client?:

ClickHouseClient
來自 @clickhouse/client、預先設定的 ClickHouse client。需要自訂請求設定時使用。與上述 credential 欄位互斥。

ttl?:

object
建立資料表時套用的各資料表 TTL 設定。接受資料列與欄位層級的 TTL,間隔單位可從 NANOSECOND 到 YEAR。

replication?:

{ cluster?: string; zookeeperPath?: string; replicaName?: string }
用於多 replica ClickHouse cluster 的選用複寫資料表設定。設定後,Mastra 會建立複寫的 MergeTree 資料表。設定 cluster 時,Mastra 也會將 ON CLUSTER 新增至 Mastra 擁有的資料定義語言(DDL)。

disableInit?:

boolean
= false
設為 true 時,store 不會在首次使用時建立資料表或執行 migration。請從部署 script 明確呼叫 storage.init()。

ClickhouseStore 也接受 ClickHouseClientConfigOptions 的所有選項(例如 database、request_timeout、compression、keep_alive 與 max_open_connections)。

複寫 cluster
「複寫 cluster」的直接連結

Mastra 透過 load balancer 寫入多 replica ClickHouse cluster 時,請使用 replication。

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',
},
})

設定 replication 時,Mastra 會將 MergeTree 與 ReplacingMergeTree 資料表 engine 改寫為 ReplicatedMergeTree 與 ReplicatedReplacingMergeTree。預設 engine 引數為:

  • zookeeperPath: '/clickhouse/tables/{shard}/{database}/{table}'
  • replicaName: '{replica}'

預設值符合最常見的自主管理慣例。若 cluster 的現有資料表使用不同版面設定(例如不含 {database} 區段的 /clickhouse/tables/{shard}/{table}),請明確設定相符的 zookeeperPath。Mastra 不會從 Keeper 讀取 cluster 慣例,因此不相符的預設值會將 Mastra metadata 寫入與 cluster 其餘部分不同的 branch。

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}',
},
})

設定 cluster 可將 ON CLUSTER 新增至 Mastra 擁有的 DDL,例如建立資料表、建立 materialized view、欄位 migration、TTL 變更與刪除資料表。

設定 cluster 時,optimizeTable() 與 materializeTtl() 等手動維護會在每個 replica 上執行。這些操作在大型 cluster 上可能耗費大量資源。建議避開尖峰時間執行,並讓例行 merge 在背景 merge queue 上發生,不要在每次重新啟動時觸發。

若現有 Mastra 資料表使用本機 MergeTree 或 ReplacingMergeTree engine,在啟用 replication 時初始化會失敗。由於跨 replica 執行複製後交換並不安全,Mastra 不會默默轉換本機資料表。請先將受影響的資料表重新建立為 Replicated*,再啟用 replication。若要安全遷移,請重新命名本機資料表、執行 CREATE TABLE ... ENGINE = ReplicatedMergeTree(...) ON CLUSTER ...、執行 INSERT INTO ... SELECT * FROM <renamed_local>,最後刪除 <renamed_local>。

請勿在 ClickHouse Cloud 上設定 replication。Cloud 會在 server 端將 MergeTree 改寫為 SharedMergeTree,明確使用 ReplicatedMergeTree engine 會產生不正確的 DDL。replication 僅適用於自主管理的多 replica cluster。

Observability domain 選項
「Observability domain 選項」的直接連結

ObservabilityStorageClickhouse 與 ObservabilityStorageClickhouseVNext 接受和 ClickhouseStore 相同的連線選項(url、username、password 或預先設定的 client)。

託管選項
「託管選項」的直接連結

ClickHouse 可在任何能透過 HTTP 連線的位置執行。常見選項包括:

本機開發時:

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',
})

使用 Railway 與類似平台部署
「使用 Railway 與類似平台部署」的直接連結

Railway、Fly.io、Render 和 Heroku 等平台會在暫時性檔案系統上執行應用程式 container。DuckDB 等嵌入式可觀測性 backend 需要可寫入且持久的本機檔案,因此在這些平台上重新啟動時會遺失資料,或完全無法部署。

請改用 ClickHouse。由於 ClickHouse 透過 HTTP 連線,因此相同連線可從任何 host 使用:

src/mastra/index.ts
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()],
},
},
}),
})

使用下列任一選項佈建資料庫:

  • 受管理:使用 ClickHouse Cloud。將 CLICKHOUSE_URL、CLICKHOUSE_USERNAME 與 CLICKHOUSE_PASSWORD 設為託管平台中的環境變數。
  • 在 Railway 自行託管:使用官方 Docker image 將 ClickHouse 服務新增至 Railway 專案,再透過 Railway 私有網路從應用程式服務參照該服務。

相同方式也適用於其他採用暫時性檔案系統的 host。若應用程式資料也應存放在 host 外,請將此設定與受管理的 PostgreSQL 或 LibSQL/Turso 執行個體搭配,作為 default storage。

警告

請勿將 DuckDB 等嵌入式 backend 指向暫時性 container 檔案系統內的路徑。container 重新啟動時,寫入該處的資料會遺失;在部分平台上,該路徑還是唯讀的。

初始化
「初始化」的直接連結

傳入 Mastra 類別時,ClickhouseStore 會自動呼叫 init() 來建立 schema,並執行任何待處理的 migration。透過 MastraCompositeStore 使用 ObservabilityStorageClickhouseVNext 時也相同。

若在 Mastra 外管理 storage,請明確呼叫 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()

在 CI/CD pipeline 中,請在 ClickhouseStore 上設定 disableInit: true,並從使用較高權限 credential 的部署步驟執行 init()。之後,runtime 應用程式 credential 可限制為讀取與插入權限。

可觀測性
「可觀測性」的直接連結

ClickHouse 是正式環境可觀測性的建議 backend:

  • Insert-only 策略:MastraStorageExporter 會批次寫入已完成的 span,不會逐一更新 span,這是可用策略中吞吐量最高者。
  • 欄式壓縮:相較於列式資料庫中的相同資料,span attribute 與 log payload 可獲得良好壓縮效果。

如需完整策略矩陣與正式環境指南,請參閱 MastraStorageExporter 參考資料。