# ヒストグラム vs サマリー

Site [llms.txt](/ja/llms.txt)

---

多くの点で、ヒストグラムとサマリーは非常に似ているように見えます。
どちらも多数のデータポイントを効率的な処理、送信、保存のためのデータ構造にまとめます。
また、どちらもデータの中央値や p99 のような任意のクォンタイルの追跡に使用できます。
では、どう違うのでしょうか。
詳しく見ていきましょう。

## ヒストグラム {#histograms}

[ヒストグラムとその有用性](/blog/2023/why-histograms/)について最近投稿したばかりなので、ここでは簡潔にまとめます。
ヒストグラムとは、データポイントの集合の分布を記述するデータ構造です。
たとえば、HTTP エンドポイントへのすべてのレスポンスタイムを収集し、0 から 1000 ミリ秒の範囲で10個のビンを持つヒストグラムとして記述できます。
各ビンは、その範囲に含まれるリクエスト数をカウントします。

![レスポンスタイムのヒストグラム](response-times-histogram.png "A histogram titled 'Response Time (1260 requests).' The y-axis is the request count and there are 12 buckets ranging from less than 10 milliseconds to greater than 1000 milliseconds. The distribution appears to be a normal bell curve with a mode in the 'less than 75 milliseconds' bucket. The 'greater than 1000' bucket shows a slight bump to indicate a long tail captured by a single bucket.")

ここから、90パーセンタイルのような φ-クォンタイルを推定できます。
1260 リクエストがあるので、1134番目（`1260 * .90`）のリクエストが90パーセンタイルを表します。
次に、バケットのカウントをその順位を超えるまで合計することで、そのリクエストが8番目のバケット（`300 <= x < 500`）に含まれることを計算できます。
最後に、バケット内の相対順位24（`1134 - 1110`）を使い、線形補間によって p90 の値を360ms（`300 + ((24 / 80) * (500 - 300))`）と推定できます。
これは _推定値_ であり、最大60ms（`360 - 300`）、相対誤差17%（`60 / 360`）の誤差が生じうることを理解しておくことが重要です。
この誤差は SLO 値の周辺に、より多くのより小さなバケットを設定することで軽減できますが、完全に排除することはできません。

ヒストグラムの重要な特性の1つは _集約可能_ であることです。
つまり、バケット境界が一致していれば、任意の数のヒストグラムをデータや精度の損失なく1つのヒストグラムに統合できます。
これは、任意の数のホストがヒストグラムデータ構造をサーバーに報告でき、サーバーはそれらをすべて1台のホストから報告されたかのように集約してクォンタイルを計算できることを意味します。
1台以上のホストから長期間にわたってヒストグラムを収集することで、開発者はデータの分布やその分布が時間とともにどう変化するかを深く理解できます。

## サマリー {#summaries}

サマリーはほぼ反対の方法で動作します。
サマリーを設定する際には、追跡する φ-クォンタイル、許容誤差範囲、および減衰率を指定します。
たとえば、サマリーは p99 ± 0.5% を減衰率5分で追跡できます。
計算はより複雑なのでここでは扱いませんが、重要な違いの1つは、値がサーバーに送信される前にクライアント側で計算されることです。
この最も重要な結果として、複数のクライアントからのサマリーは _集約できません_ 。
もう1つの欠点は、任意の φ-クォンタイルをクエリできず、事前に設定・収集したクォンタイルしか利用できないことです。

これらの欠点がある一方で、サマリーにはいくつかの利点もあります。
まず、クライアント側でわずかなパフォーマンスコストを引き換えに、送信、保存、サーバー処理のコストを大幅に削減できます。
上記のヒストグラムの例では、分布は12個の個別の時系列で表されています。
各バケットに1つのカウンター + 範囲外の値用に1つのバケット + 全値の合計です。
これは属性によるカーディナリティの増加がない、比較的控えめな単一のヒストグラムでの話です。
一方、サマリーは事前計算された `p99` 値に対して1つの時系列のみです。
次に、サマリーは非常に低く設定可能な相対誤差率を持ちます。
上記のヒストグラムの例では17%の相対誤差の可能性がありましたが、サマリーは ± 0.5% の精度が保証されます。

## どちらを選ぶべきか {#so-which-should-you-choose}

残念ながら答えは「場合による」であり、万能の解決策はありません。
多くのソースからデータを集約する必要がある場合は、ヒストグラムが正しい選択かもしれません。
非常に厳密な SLO を持つ大量の個別メトリクスを収集している場合や、Prometheus サーバーのリソースが特に制約されている場合は、サマリーが正しい選択かもしれません。
柔軟なクエリのためにいくつかのヒストグラムを使い、高精度で低コストなアラートのためにいくつかのサマリーを使うハイブリッドが理想的な解決策かもしれません。
自分のシステムの詳細を知り、正確で柔軟かつ特定のニーズに合ったオブザーバビリティソリューションを設計できるのは自分だけです。
重要なのは、利用可能なツールの強みと制限を理解し、情報に基づいた意思決定ができるようになることです。

## ボーナスラウンド: ネイティブ/指数ヒストグラム {#bonus-round-nativeexponential-histograms}

この件についてはより長い記事を予定しているので手短にしますが、ヒストグラムの主な欠点の多くは指数ヒストグラムによって軽減されます。
指数ヒストグラムは、Prometheus ではネイティブヒストグラムと呼ばれています。
Prometheus では v2.40.0 以降の実験的機能として利用可能であり、OpenTelemetry 仕様では v1.17.0 で安定版になっています。
指数ヒストグラムにはいくつかの利点があります。

- 非常に効率的なデータ収集と送信
- ヒストグラムあたり一定数の時系列の生成（かつその数もより少ない）
- 非常に低い相対誤差率
- 自動的なバケット境界により、設定と使用がシンプル

これらの利点は、従来の明示的バケット定義の方法ではなく、スケールファクターに基づいてバケット境界を定義し、分布の変化に応じてバケットを適切にリサイズすることで実現されます。
現在のヒストグラムやサマリーの状態に満足していない場合は、指数ヒストグラムを試してみることをおすすめします。
この記事の執筆時点では、ネイティブヒストグラムに関する公式の Prometheus ドキュメントはありませんが、近日中に詳しい説明を追加する予定です。

それまでの間、参考になるトークを紹介します。

- [PromCon EU 2022 - Native Histograms in Prometheus - Ganesh Vernekar](https://promcon.io/2022-munich/talks/native-histograms-in-prometheus/)
- [KubeCon EU 2023 - Prometheus Native Histograms in Production - Björn Rabenstein, Grafana Labs](https://www.youtube.com/watch?v=TgINvIK9SYc)
- [Using OpenTelemetry's Exponential Histograms in Prometheus - Ruslan Kovalov & Ganesh Vernekar](https://www.youtube.com/watch?v=W2_TpDcess8)

_この記事は、著者のブログに[もともと掲載された][originally posted]ものです。_

[originally posted]: <https://dyladan.me/histograms/2023/05/03/histograms-vs-summaries/>
