本記事は「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 |
この結果から 3 つのことが読み取れます。
- Elasticsearch と OpenSearch は検索系(Q19、Q18)で競争力があります。
- ClickHouse はほとんどのクエリで 2.3〜2.9 秒前後にとどまり、Q19 では 30.816 秒かかっています。
- 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 です。
- 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 つです。
- 検索性能と、検索後の分析性能は別の問題です。検索に強いシステムでも、分析ではコストが高くつくことがあります。
- ペイロードはチームの想定より速く広がる一方、ホットパスは少数にとどまります。そのため、ストレージは最初からこの 2 つの層を異なる方法で扱うべきです。
Doris の優位性は、動的フィールドをプルーニング、インデックス、集計が可能なカラムナ構造に変える VARIANT から来ています。エージェントがより自律的になり、1 リクエストあたりのデータ量が増えるほど、この点は重要になります。ペタバイト規模の実例としては、StepFun が Apache Doris でエージェントオブザーバビリティ基盤を構築した事例があります。
なお、ベンチマークで使われた VARIANT、転置インデックス、キャッシュの各機能は、マネージドサービスの VeloDB Cloud でも利用できます(無料トライアル:SaaS は 14 日間、BYOC はコンピューティング費用 90 日間)。

