0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

エージェントログの動的JSON分析:Doris vs ClickHouse・ES

0
Posted at

本記事は「Dynamic JSON in Agent Workloads: Apache Doris vs ClickHouse, Elasticsearch, and OpenSearch」(https://www.velodb.io/blog/dynamic-json-in-agent-workloads-apache-doris-clickhouse-elasticsearch-and-opensearch )を日本語に翻訳・再構成したものです。

はじめに

AI エージェントが出力するオブザーバビリティログには、どんどん増え、形を変え続ける JSON ペイロードが含まれます。Apache Doris は、こうしたエージェントログ内の動的 JSON を、他の選択肢よりも大幅に低いレイテンシで分析できます。

AgentLogsBench の 1 億行データセットにおける動的 JSON のコアクエリでは、ClickHouse のレイテンシは Doris の中央値レイテンシの約 7.4 倍、Elasticsearch と OpenSearch は約 2.4 倍(いずれも幾何平均)でした。この差を生んでいるのが Doris の VARIANT 型 で、頻繁にクエリされる JSON パスを型付きのカラムナサブカラムに変換します。

本記事は、AgentLogsBench の設計目標と全体結果を紹介した前回の記事の続編です。

要点まとめ

  • 1 億行において、JSON 系クエリ(Q07、Q10、Q12、Q16、Q17、Q18、Q20)の平均レイテンシは Doris が最小でした。ClickHouse は Doris の約 7.4 倍、Elasticsearch と OpenSearch は約 2.4 倍です。
  • ClickHouse との差が最も大きいのは Q17 で、Doris 0.032 秒に対して ClickHouse 2.339 秒(約 70 倍)でした。
  • 検索と集計を組み合わせた Q19 では Elasticsearch が健闘し、Doris 1.013 秒に対して 0.989 秒でした。ClickHouse は Q19 に 30.816 秒かかっています。
  • 1 億行時のストレージ使用量は、ClickHouse 53.8 GB、Doris 62.2 GB、Elasticsearch 191.9 GB、OpenSearch 194.7 GB です。Doris は全文検索にも対応しつつ、ClickHouse との差は 16% 以内に収まっています。
  • Doris の優位性は VARIANT に由来します。ホットな JSON パスは型付きカラムになり、ロングテールのパスはスパースカラム(sparse columns)または DOC モードに格納されます。

エージェントが生成するログの形

エージェントのログは横に広がり続けています。かつてのログエントリはタイムスタンプ、ログレベル、メッセージ程度でした。今では 1 回の呼び出しに、モデルパラメータ、ツール呼び出し、検索(retrieval)結果、プロンプトのバージョン、ユーザーコンテキストなどが含まれます。

こうしたフィールドに対して事前にスキーマを設計することはできないため、自然と JSON がその入れ物になります。

1 つのユーザーリクエストは、一連の observation から成るトレースになります。プランニング、モデル呼び出し、停止理由(stop reason)、トークン数、ツール呼び出し、終了コード、stderr、検索、スコアリング、そして最終回答です。

トレース ID、タイムスタンプ、レイテンシ、コスト、イベント種別といった安定したフィールドは通常のカラムに置き、変化し続けるフィールドはペイロードに入れる、というのが基本的な形です。

{
  "event_time": "2026-04-01T12:00:00Z",
  "trace_id": "trace_000001",
  ...
  "payload": {
   "provider": {
    "stop_reason": "tool_use",
    "cache_hit": false
   },
   "tool_result": {
    "stderr": "unable to open ...",
    "exit_code": 1
   },
   "otel": {
    "status_code": "ERROR"
   }
  }
 }

ペイロードは誰にもコントロールできないペースで変化します。最初は 30 フィールドだったペイロードが、1 四半期のうちに数千フィールドに達することもあります。

そこで核心となる問いは、ペイロードが数千フィールドに膨らんだとき、データベースは動的フィールドを通常のカラムと同じ速さで分析できるか という点です。

AgentLogsBench は JSON 処理効率をどう測るか

AgentLogsBench は、エージェントの observation データを生成し、各システムにロードし、同じクエリを各システムで実行します。

ひと口に「JSON サポート」と言っても、文字列として保存して読み取り時にパースする方式から、書き込み時に型付きカラムへ分解(shredding)する方式まで、設計は大きく異なります。このベンチマークはその違いを直接計測します。

ルールは以下のとおりです。

  • すべてのクエリは 1 つのテーブル agent_observations に対して実行する。
  • どのシステムも、JSON の事前フラット化、補助テーブルへのフィールド分割、ロード前に全パスを事前定義することは禁止。
  • クエリは実際のデバッグ作業に沿ったものとする。payload.attr パスでのフィルタ、停止理由の集計、動的フィールドのファセット、プロンプトテンプレートバージョン別の集計、テキスト検索と集計の組み合わせなど。

メインの計測は 1 億行で、各クエリの中央値レイテンシを採用しています。

項目 内容
構成 シングルノード、AWS m6i.8xlarge(32 vCPU、128 GiB メモリ、gp3 SSD)
OS Ubuntu 24.04
バージョン Apache Doris 4.1.0-rc01、ClickHouse 26.2.13.2、Elasticsearch 9.3.0、OpenSearch 3.6.0

詳細と全結果は AgentLogsBench で公開されています。

なぜこのワークロードではクエリレイテンシが決定的なのか

  • デバッグは対話的かつ逐次的:エンジニアは 1 回のセッションで、前の結果に依存するクエリを十数回以上実行します。そのためレイテンシは積み上がっていきます。
  • 評価ループは常に回っている:プロンプト別、モデル別、ツール別、コスト別の集計が、同じ動的フィールドに対して絶えず実行されます。
  • ダッシュボードはファンアウトする:1 つのインシデントページが 15 個の集計を発行することもあり、最も遅いクエリがページの表示時間を決めます。

1 クエリ 300ms なら「データとの対話」ですが、3 秒になると「レポートの実行」になってしまいます。ストレージサイズは保持コストを決め、クエリレイテンシは人がそのツールを使い続けるかどうかを決めます。

動的 JSON クエリセットのレイテンシ

1 億行における Q07、Q10、Q12、Q16、Q17、Q18、Q20 の幾何平均では、ClickHouse が Doris の約 7.4 倍、Elasticsearch と OpenSearch が約 2.4 倍でした。

1 億行時の中央値レイテンシ(小さいほど良い、太字は各行の最速値):

クエリ シナリオ Doris ClickHouse Elasticsearch OpenSearch
Q07 変化する payload.attr に対する複数条件フィルタ 1.497s 2.904s 1.800s 1.819s
Q10 プロバイダの停止理由とキャッシュヒットの集計 0.315s 2.448s 1.959s 2.071s
Q12 動的フィールドのファセット集計 0.570s 2.656s 1.218s 1.259s
Q16 低カーディナリティフィールドの複数条件フィルタ 0.113s 2.715s 0.810s 0.768s
Q17 高カーディナリティなリクエストキーでのフィルタ 0.032s 2.339s 0.057s 0.053s
Q18 プロンプトテンプレートバージョン別の性能集計 1.169s 2.760s 1.114s 1.155s
Q19 インシデント集計とテキストトークン検索 1.013s 30.816s 0.989s 1.333s
Q20 ワークフローとポリシーパック別の集計 0.629s 2.592s 1.359s 1.508s

コア動的JSONクエリの相対レイテンシ(幾何平均、Doris = 1.0x)

この結果から 3 つのことが読み取れます。

  1. Elasticsearch と OpenSearch は検索系(Q19、Q18)で競争力があります。
  2. ClickHouse はほとんどのクエリで 2.3〜2.9 秒前後にとどまり、Q19 では 30.816 秒かかっています。
  3. Doris が最も大きな差をつけているのは集計、ファセット、ロールアップ系(Q10、Q12、Q16、Q20)で、0.113〜0.629 秒です。

ペイロード集計系のクエリは、検索の「後」に行う分析そのものです。Q17 はその差をよく表しています。

1 億行時のストレージフットプリント

Doris は 62.2 GB で、ClickHouse(53.8 GB)との差は 16% 以内、Elasticsearch(191.9 GB)や OpenSearch(194.7 GB)の約 3 分の 1 です。

1億行時のディスク上ストレージ使用量(GB、小さいほど良い)

  • ClickHouse の使用量が最も少ないのは、カラムナ圧縮の特性と一致しています。
  • Elasticsearch と OpenSearch は、転置インデックス、ターム辞書、フレーズクエリ用の構造を保持するため、使用量が大きくなります。
  • Doris は全文検索と動的ペイロードのクエリを同時に提供しています。VARIANT、転置インデックス、SQL 集計、キャッシュを 1 つのカラムナエンジンの中にまとめているのが特徴です。

Doris VARIANT:動的 JSON をカラムナ実行パスに取り込む

JSON パスからカラムナサブカラムへ

Doris の VARIANT は、頻繁に使われる JSON パスを内部的なカラムナサブカラムに変換します。このベンチマーク結果を生み出しているのは、まさにこの変換です。

書き込み時に Doris はパスを解析し、型を推論し、サブカラム化します。読み取り時、ユーザーは通常の JSON パス式をそのまま書くだけです。以下は Q12 を簡略化した SQL で、選択したイベント種別について、リリースリングと顧客ティアごとに件数、平均レイテンシ、コスト合計を集計します。

SELECT
    CAST(payload['attr']['release_ring'] AS STRING) AS release_ring,
    CAST(payload['attr']['customer_tier'] AS STRING) AS customer_tier,
    count(*) AS observations,
    avg(latency_ms) AS avg_latency_ms,
    sum(total_cost) AS total_cost
FROM agent_observations
WHERE type IN ('GENERATION', 'TOOL', 'RETRIEVAL')
GROUP BY
    CAST(payload['attr']['release_ring'] AS STRING),
    CAST(payload['attr']['customer_tier'] AS STRING)
ORDER BY observations DESC
LIMIT 50;

一見するとペイロード全体をスキャンしているように見えますが、実際にエグゼキュータが読むのは型付きのサブカラム 2 本だけです。カラムプルーニング、ベクトル化実行、辞書エンコーディングと圧縮、インデックスによるフィルタリングが効くため、Q12 は約 0.57 秒で完了します。

従来の JSON クエリは、大きなドキュメントの中を毎回探索します。VARIANT は書き込み時に頻出パスを抜き出しておくことで、それらを通常のカラムと同等の性能で扱えるようにしています。

ワイド JSON のボトルネック:ホットパスとロングテールの混在

ペイロードは広がっていきますが、その広がり方は均一ではありません。リリースリング、顧客ティア、キャッシュヒット、停止理由のような少数のパスは「ホット」で、ほぼすべてのセッションで使われます。

payload.attr.release_ring
payload.attr.customer_tier
payload.provider.cache_hit
payload.provider.stop_reason

一方で、モデル、ツール、プラグイン、顧客ごとの設定の違いから生まれる数千のパスがロングテールを形成し、それぞれは月に 1 回程度しかクエリされないかもしれません。

すべてのパスを同じように扱うシステムでは、ホットな 4 フィールドだけを使うクエリでも、無関係な数千のフィールドに足を引っ張られます。

Doris はこの 2 つの層を別々に扱います。ホットパスはカラムになり、コールドなパスはスパースカラムまたは DOC モードに格納されます。ワイド JSON に対しては Storage Format V3 が推奨されています。V3 は VARIANT が大量の動的サブカラムを生成する場合に、カラムメタデータをセグメントフッターから切り離します。これによりファイルのオープンが速くなり、メモリオーバーヘッドが下がり、ホットフィールドは通常のカラムと同じ速度を保てます。

他のシステムは動的 JSON をどう扱っているか

DuckDB と Parquet Variant:優れたオープンフォーマット、オンライン分析には限界

Parquet Variant と DuckDB Variant は優れたオープンフォーマットです。JSON 文字列を型付きのバイナリ表現に変換し、頻出フィールドを型付きカラムに shredding でき、データレイクハウスでのデータ交換、ローカル分析、複数エンジン間での読み書きに適しています。

ただし 1 億行の計測では、DuckDB のコアクエリのレイテンシは約 283 秒(282.798s)から約 7,415 秒(7414.692s)で、Doris の 0.032〜1.497 秒とは大きく開きがありました。これは両者が解いている問題が違うためです。オープンフォーマットはポータブルなストレージに主眼を置き、Doris VARIANT は動的 JSON をカラムナストレージ、インデックス、コンパクション、ベクトル化実行に取り込み、オンライン分析を行うことに主眼を置いています。

Elasticsearch と OpenSearch:検索は強いが、動的集計は高コスト

Elasticsearch と OpenSearch は検索(Q17、Q19)に強みがあります。

一方で、dynamic mapping はフィールド爆発(field explosion)の影響を受けやすい構造です。エージェントのペイロードは payload.attr.*、payload.tool_result.*、payload.otel.* やプラグイン由来のフィールドなど、ロングテールのフィールドを次々に生み出します。これらをすべて集計可能なフィールドとしてマッピングすると、mapping、doc values、ヒープ、セグメントメタデータのコストが膨らみます。

ClickHouse JSON:圧縮は優秀、ロングテールパスには実コスト

ClickHouse の JSON 型はサブカラムに対応しており、shared data の扱いも改善が続いています。ただし動的パスの数が max_dynamic_paths(デフォルト 1024)を超えると、ロングテールのパスは shared data に入り、クエリ時に追加の読み取りとフィルタリングが必要になります。

バージョン 25.8 では、バケット化された高度な shared data シリアライズが追加され、無関係なサブストリームを読まずに目的のパスのデータへより正確にジャンプできるようになりました。ただしこれにはコストもあります。JSON 全体の読み取りやマージが遅くなる可能性があるため、ClickHouse は元の形式のコピーを別途保持し、その分ストレージのオーバーヘッドが増えます。

一覧表:各システムは JSON をどう理解しているか

システム JSON のモデル化方法 強み 主なコスト
Doris データベースネイティブなカラムナ VARIANT 動的フィールドのフィルタ、SQL 集計、全文検索の連携 ストレージは小さいが絶対的な最小ではない
ClickHouse 動的サブカラム + shared data 高い圧縮率、成熟したカラムナ分析 shared data 側のパスのクエリが高コスト
Elasticsearch / OpenSearch 検索ドキュメントと転置インデックス 全文検索、ドキュメントリコール、高カーディナリティフィルタ フィールド爆発と集計コスト
DuckDB / Parquet Variant オープンファイルフォーマット + ローカル分析層 レイクハウスでのデータ交換、ローカル分析、オープンなエンコーディング オンラインのワイド JSON 分析には限界
PostgreSQL JSONB 行指向で格納された JSON ドキュメント 幅広い適用範囲、成熟したエコシステム 大規模な対話的分析では制約がある

Doris は動的 JSON を自身のカラムナストレージ、インデックス、ファイルフォーマットの中に吸収しています。他のシステムは、それぞれ元々の設計の枠内で JSON に対応しています。

エージェントトレース用データストアの選び方

AgentLogsBench で見られた 7.4 倍の差は、個々の JSON 関数の速さではなく、各システムが動的 JSON をどう扱うかというアーキテクチャの違いを反映しています。

ペイロードは広がり続け、フィールドは変化し続けますが、クエリは少数のビジネス上重要なパスに集中します。重要なのは、それらの動的パスをカラムナストレージ、インデックス、圧縮、ベクトル化実行に乗せられるかどうかです。それが、検索結果が返ってきた「後」の分析体験を左右します。

ここから得られる教訓は 2 つです。

  1. 検索性能と、検索後の分析性能は別の問題です。検索に強いシステムでも、分析ではコストが高くつくことがあります。
  2. ペイロードはチームの想定より速く広がる一方、ホットパスは少数にとどまります。そのため、ストレージは最初からこの 2 つの層を異なる方法で扱うべきです。

Doris の優位性は、動的フィールドをプルーニング、インデックス、集計が可能なカラムナ構造に変える VARIANT から来ています。エージェントがより自律的になり、1 リクエストあたりのデータ量が増えるほど、この点は重要になります。ペタバイト規模の実例としては、StepFun が Apache Doris でエージェントオブザーバビリティ基盤を構築した事例があります。

なお、ベンチマークで使われた VARIANT、転置インデックス、キャッシュの各機能は、マネージドサービスの VeloDB Cloud でも利用できます(無料トライアル:SaaS は 14 日間、BYOC はコンピューティング費用 90 日間)。

参考リンク

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?