跳至主要內容

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 支援 memoryworkflowsobservability 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 })

ObservabilityStorageClickhouseObservabilityStorageClickhouseVNext 也接受相同的 client 形式。

設定
「設定」的直接連結

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

id:

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

url?:

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

username?:

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

password?:

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

client?:

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

ttl?:

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

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 的所有選項(例如 databaserequest_timeoutcompressionkeep_alivemax_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 會將 MergeTreeReplacingMergeTree 資料表 engine 改寫為 ReplicatedMergeTreeReplicatedReplacingMergeTree。預設 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 資料表使用本機 MergeTreeReplacingMergeTree 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 選項」的直接連結

ObservabilityStorageClickhouseObservabilityStorageClickhouseVNext 接受和 ClickhouseStore 相同的連線選項(urlusernamepassword 或預先設定的 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 與類似平台部署」的直接連結

RailwayFly.ioRender 和 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_URLCLICKHOUSE_USERNAMECLICKHOUSE_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 參考資料