高速なClickHouseにも厳密な監視が不可欠な理由
ClickHouseは毎秒数億件ものレコードを容易にスキャンできます。しかし、1日あたり5億から数十億件のログを扱う本番環境(プロダクション)では、運用のボトルネックが発生し始めます。些細なミスひとつでサーバー全体が応答停止(ハングアップ)に追い込まれることもあります。
- フィルタ条件不足のクエリによるメモリ枯渇: 開発者が
WHERE date >= today()による絞り込みを忘れ、カーディナリティの高いカラムに対してGROUP BYを実行してしまうケースです。その結果、プロセスはわずか5秒で64GBのRAMを食いつぶし、LinuxのOOM Killerが即座に介入してClickHouseプロセスを強制終了(Kill)します。 - Part Mutationの滞留(キュー詰まり): ClickHouseは
ALTER UPDATE/DELETEを非同期のMutationメカニズムとして処理し、データパート全体を再書き込みします。Mutationを連続して実行するとディスクI/Oが100%に達し、これに伴って多数の読み取りクエリがタイムアウトを起こします。 - パート過多エラー("Too many parts in all data parts in table"): アプリケーション側が極端に小さなバッチ(50,000件にまとめるのではなく100件ずつなど)でInsertを繰り返すと、ClickHouse内に膨大なゴミファイルが生成されます。バックグラウンドでのマージ処理が追いつかなくなり、データベースは自己防衛のために新規の書き込みリクエストをすべてブロックします。
これまで障害が発生するたび、チームは慌てて対象ノードにSSH接続し、clickhouse-clientからsystem.processesテーブルを必死にクエリするのが常でした。しかし現在では、ClickHouseのコアに標準搭載されているOpenMetricsエンドポイントを活用するだけで、Prometheusから継続的にメトリクスを収集(スクレイプ)できます。
Docker Composeによる検証環境の構築
ステージング環境や本番サーバーで既にClickHouseが稼働している場合は、後述のXML設定セクションへ直接進んでください。メトリクスのスクレイプ動作を手軽に確認したい場合は、2分ほどで以下のコンテナクラスタを立ち上げられます。
# 作業ディレクトリの作成
mkdir -p ~/clickhouse-monitor && cd ~/clickhouse-monitor
# docker-compose.yml ファイルの作成
cat << 'EOF' > docker-compose.yml
version: '3.8'
services:
clickhouse:
image: clickhouse/clickhouse-server:23.8
container_name: clickhouse-server
ports:
- "8123:8123" # HTTP インターフェース
- "9000:9000" # ネイティブ TCP クライアント
- "9363:9363" # Prometheus メトリクスポート
volumes:
- ./ch-config.xml:/etc/clickhouse-server/config.d/prometheus.xml:ro
- ch_data:/var/lib/clickhouse
ulimits:
nofile:
soft: 262144
hard: 262144
prometheus:
image: prom/prometheus:v2.47.0
container_name: prometheus-ch
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
grafana:
image: grafana/grafana:10.1.0
container_name: grafana-ch
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin
volumes:
ch_data:
EOF
ClickHouseのネイティブメトリクスエンドポイントを有効化する
1. Prometheus用のXML設定ファイルを作成する
サードパーティ製のclickhouse_exporterのような外部エクスポーターを追加インストールする必要はありません。ClickHouseにはOpenMetricsモジュールが標準で組み込まれています。/etc/clickhouse-server/config.d/ディレクトリに設定ファイルを配置するだけで完了します。
<clickhouse>
<prometheus>
<endpoint>/metrics</endpoint>
<port>9363</port>
<metrics>true</metrics>
<events>true</events>
<asynchronous_metrics>true</asynchronous_metrics>
<status_info>true</status_info>
</prometheus>
</clickhouse>
これら4つのフラグは、以下の内部テーブルグループに対応しています。
metrics:system.metricsからの瞬時ステータス(アクティブなクエリ数、ビジー状態のバックグラウンドスレッドなど)。events:system.eventsからの累積カウンタ(実行済みクエリ総数、ディスクからの読み取り/書き込みバイト数など)。asynchronous_metrics:system.asynchronous_metricsから定期的に取得されるスナップショット(RAM RSS、未マージのパート数、CPU使用状況など)。status_info: ノード全体の接続ステータスおよびヘルス状態。
2. Prometheusのスクレイプジョブ設定
prometheus.ymlを作成します。ここではサンプリング間隔を10秒ごとに設定します。
global:
scrape_interval: 10s
evaluation_interval: 10s
scrape_configs:
- job_name: 'clickhouse'
static_configs:
- targets: ['clickhouse:9363']
labels:
cluster: 'analytics-production'
env: 'prod'
システム全体を起動します。
docker-compose up -d
データの検証とダッシュボードの設定
1. curlによる生メトリクスの確認
Grafanaでグラフを描画する前に、ポート9363からデータが正しく出力されていることを確認します。
curl -s http://localhost:9363/metrics | grep -E 'ClickHouseProfileEvents_Query|ClickHouseAsyncMetrics_MemoryTracking'
出力結果に数値を含むテキスト行が表示されれば成功です。Prometheusはこのデータを正常にパースできます。
2. 本番環境で役立つ最重要PromQLクエリ
http://localhost:3000からGrafanaにログインします(デフォルトアカウント: admin/admin)。Data Sourceにhttp://prometheus:9090を指定した上で、以下の3つの重要アラートグループの設定に注力します。
A. クエリトラフィックとディスクI/O負荷
このグループは、CPUやディスクのボトルネックを引き起こすクエリスパイクの検知に役立ちます。
# 1秒あたりのクエリ発生頻度(QPS)
rate(ClickHouseProfileEvents_Query[1m])
# サーバー上で同時に実行されているクエリ数
ClickHouseMetrics_Query
# ディスクからのデータ読み取り速度(Bps - Bytes per second)
rate(ClickHouseProfileEvents_ReadBufferFromFileDescriptorBytes[1m])
B. Part Mutationとバックグラウンドマージ
ここは最もリスクの高い領域です。これら2つの指標が急増している場合、システムに技術的負債としての負荷が集中しています。
# 未処理のMutation数(この値が20を超えて継続的に増加する場合は、直ちにALTERを停止する必要があります)
ClickHouseAsyncMetrics_NumberOfMutations
# バックグラウンド処理プールを占有しているマージおよびMutationタスク数
ClickHouseMetrics_BackgroundMergesAndMutationsPoolTask
# 1パーティションあたりの最大パート数(150〜300パートを超えると危険水域)
ClickHouseAsyncMetrics_MaxPartCountForPartition
C. RAM使用量とOOMクラッシュの防止
ClickHouseは独自のトラッキング機構を提供していますが、OS側の実メモリとも照合する必要があります。
# ClickHouse内部メカニズムによって算出された追跡メモリ使用量
ClickHouseMetrics_MemoryTracking
# プロセスがOSから実際に占有している実メモリ(Resident Set Size - RSS)
ClickHouseAsyncMetrics_MemoryResident
実践のポイント: サーバーの物理RAMの85%にClickHouseAsyncMetrics_MemoryResidentが達した時点でアラートルールを発火させるように設定してください。95%まで待ってはいけません。巨大なクエリが1つ走るだけで、残りの10%はわずか2〜3秒で食いつぶされてしまうからです。
3. 定番ダッシュボードのインポート
すべてのパネルを一から手動で作成する必要はありません。ClickHouseコミュニティによって、非常に洗練されたダッシュボードテンプレートが用意されています。
Grafanaを開き、Dashboards > Import を選択して、ID 14192(ClickHouse Overview)または 882 を入力します。これにより、Thread Pool、Connection Count、Cache Hit RateからZooKeeper/Keeperの同期レイテンシに至るまで、詳細な可視化グラフを即座に利用できます。

