TL

メトリクスの基数爆発とその抑制

監視基盤が突然重くなる原因を断つ。ラベルの直積で時系列が指数的に膨らむ基数爆発の機構と、集約・サンプリング・exemplarによる抑制原理をTSDBの内部構造から理解できます。

応用PrometheusメトリクスTSDBオブザーバビリティ監視最終更新: 2026-06-21
TL;DR要点だけ先に
  • 1.時系列数はメトリクス名とラベル値の直積で決まり、ラベルを掛け合わせるほど指数的に増える。これが基数爆発。
  • 2.PrometheusのTSDBは時系列ごとにメモリ上のheadチャンクと索引を持つため、基数の増大はメモリ・索引・クエリ全体を直撃する。
  • 3.抑制は3層。高基数ラベルを集約で落とす/recording ruleで事前集約/個別の事例はexemplarでトレースへ逃がす。

基数(cardinality)とは何か

メトリクスの世界で言う 基数(cardinality) とは、区別される時系列(time series)の総数 を指します。Prometheus において1本の時系列は「メトリクス名」と「ラベルの集合」の組で一意に決まります。たとえば次は別々の時系列です。

http_requests_total{method="GET",  status="200", path="/login"}
http_requests_total{method="POST", status="500", path="/cart"}

同じ http_requests_total という名前でも、ラベルの値が1つでも違えば 完全に独立した時系列 として扱われます。ここが基数を理解する出発点です。集計済みで軽いはずのメトリクスが基盤を圧迫する原因は、ほぼすべてこの「時系列の本数」に帰着します。

基数爆発の機構:ラベルの直積

時系列の総数は、各ラベルが取りうる値の数の 直積(デカルト積) で決まります。あるメトリクスのラベルが method(3種)・status(5種)・path(200種)だとすると、最悪ケースの時系列数は次のように掛け算で効きます。

3 × 5 × 200 = 3,000 系列

問題は、ここに 高基数ラベル を1つ足したときです。たとえば user_id(10万種)を加えると、

3 × 5 × 200 × 100,000 = 3億 系列

ラベルを1本足しただけで、時系列数が桁違いに膨れ上がりました。これが 基数爆発(cardinality explosion) です。各ラベルの値域が乗算で結合するため、増え方は加算ではなく 乗算的(実質的に指数的) になります。

高基数ラベルの典型例

user_idrequest_idemailsession_idfull_url(クエリ文字列込み)・コンテナの pod_nameinstance のような値の種類が無限に近い属性をラベルにすると、即座に爆発します。とくに「いつか役立つかも」でIDをラベル化するのは禁物です。

なぜ TSDB に重いのか:格納コストの内訳

Prometheus の時系列DB(TSDB)は、時系列1本ごとに独立した格納構造 を持ちます。だから本数の増加がそのままコストになります。コストは大きく3つに分かれます。

コスト要素何が起きるか基数との関係
メモリ(head)直近データは head チャンクとして全時系列ぶんメモリ常駐系列数に比例して常駐メモリが増える
索引(index)ラベル→系列の転置索引(posting list)を保持ラベル値の種類が増えるほど索引が肥大
クエリPromQL は索引で系列を引いてから走査するマッチする系列数が多いほど遅く重い

ポイントは head(メモリ上の直近ブロック) です。Prometheus はスクレイプした最新データを、いったん時系列ごとのチャンクとしてメモリに載せます。サンプル1点のデータ量は圧縮で小さくても、「アクティブな時系列の本数」ぶんだけチャンクと索引エントリが常駐 するため、系列数が増えるとメモリが線形に膨らみます。数百万系列を超えたあたりからメモリ枯渇(OOM)が現実的な脅威になります。

“チャーン”という見えにくい爆発

デプロイのたびに pod_nameinstance が変わると、古い時系列が役目を終え、新しい時系列が次々生まれます。これを チャーン(churn) と呼びます。瞬間の系列数は一定でも、索引には消えた系列のエントリが残り続け、保持期間内のユニーク系列総数が膨張します。「常時は軽いのにデプロイ後に重い」典型がこれです。

抑制の原理(1):集約で次元を落とす

最も効くのは、そもそも 不要なラベルを持たせない/集約で消す ことです。ダッシュボードやアラートで「ユーザー単位の内訳」が要らないなら、user_id はメトリクスに載せず、sum without(user_id) 的に次元を畳んでしまえば、直積の項が1つ消え、系列数が劇的に減ります。

設計原則はシンプルで、ラベルは「集計軸として実際に使う属性」だけにする ことです。可観測性の三本柱(/devops/observability/)で言えば、メトリクスは傾向把握、個別事例の追跡はログ・トレースの役割。役割分担を守るのが基数を抑える本質です。

抑制の原理(2):事前集約とサンプリング

次の層は 格納の前後で量を削る 手段です。

  • recording rule(事前集約):頻用するクエリ結果を定期的に計算し、集約済みの新しい時系列として保存 する。生の高基数メトリクスは短い保持期間に留め、ダッシュボードは事前集約済みの低基数メトリクスを参照する。クエリ時の系列走査量を恒常的に下げられる。
  • メトリクス・リラベル(drop/keep):スクレイプ時に metric_relabel_configs で不要なラベルや系列を取り込む前に捨てる。爆発源を入口で止める最終防衛線。
  • 集約サンプリング:エージェント層(OpenTelemetry Collector 等)で、生メトリクスを集約・間引きしてから送る。送信前に次元を落とすことで、TSDB に届く本数自体を減らす。
集約の順序を間違えない

recording rule で集約するときは、残したいラベルを by() / without() で明示します。sum(rate(http_requests_total[5m])) by (status) のように集約軸を絞れば、pathinstance の直積が消え、結果系列が激減します。「全ラベル込みで rate を取ってから集約」では、生の系列を全走査するので軽くなりません。

抑制の原理(3):exemplar でトレースへ逃がす

「集約すると個別の遅いリクエストが追えなくなるのでは」という懸念に答えるのが exemplar(エグザンプラ) です。exemplar は、集約されたメトリクス(とくにヒストグラム)のサンプル点に、代表的な1リクエストの trace_id を“添付”する 仕組みです。

# ヒストグラムのバケットに、その値を生んだ代表リクエストの trace_id を紐づける
http_request_duration_seconds_bucket{le="0.5"} 24054 # {trace_id="abc123"} 0.48

メトリクス本体は 低基数のままtrace_id はラベルではなく exemplar として別枠で保持される)に保ちつつ、「このp99の山を作った実例はこのトレース」という橋渡しができます。つまり、基数を増やさずに、メトリクスから個別事例(トレース)へジャンプできる。集約で失った粒度を、トレース側で補う設計です。具体的な追跡は /devops/distributed-tracing/ に委ねられます。

役割分担で考えると迷わない

高基数の情報は「ラベル(=系列を増やす)」ではなく「exemplar・ログ・トレース(=系列を増やさない)」に載せる。これが鉄則です。メトリクスは“何かおかしい”を安く広く、個別の“なぜ”はトレース/ログに逃がす。

まとめ

  • 時系列数は メトリクス名 × 各ラベルの値域の直積 で決まり、高基数ラベルを1本足すだけで乗算的に膨らむ。これが基数爆発。
  • Prometheus の TSDB は 系列ごとに head チャンクと索引 を持つため、本数増加が メモリ・索引・クエリ を同時に直撃する。チャーンによる索引肥大も見落とせない。
  • 抑制は3層。(1) ラベル設計と集約で次元を落とす(2) recording rule・リラベル・集約サンプリングで本数を削る(3) exemplar で個別事例をトレースへ逃がす
  • 容量設計の観点は /devops/capacity-planning/、指標そのものの目標設計は /devops/sre-slo/ と併せて考えると、抑制の判断基準が定まります。

DevOps/インフラ Article

メトリクスの基数爆発とその抑制を実務で読む

TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。

解決すること

Prometheus

比較で見る軸

難易度: advanced / カテゴリ: DevOps/インフラ / タグ数: 5

導入後に効く点

PrometheusのTSDBは時系列ごとにメモリ上のheadチャンクと索引を持つため、基数の増大はメモリ・索引・クエリ全体を直撃する。

先に潰すリスク

用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。

数字・仕様の読み方
難易度
advanced
カテゴリ
DevOps/インフラ
タグ数
5

判断チェックリスト

  • 自社の用途が「Prometheus / メトリクス」に近いか確認する。
  • 強みである「時系列数はメトリクス名とラベル値の直積で決まり、ラベルを掛け合わせるほど指数的に増える。これが基数爆発。」が本当に評価軸になるか確認する。
  • 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
  • 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
  • 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
  • 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。

次に確認する観点

PrometheusメトリクスTSDBオブザーバビリティ監視PrometheusメトリクスTSDB