すべてのプロダクト
Search
ドキュメントセンター

Simple Log Service:JSON ログのクエリと分析に関するよくある質問

最終更新日:Jun 03, 2026

Simple Log Service (SLS) で JSON 形式のログのクエリと分析を行う際の一般的な質問と解決策 (インデックス設定、JSON 関数、JSON 配列の処理など) を説明します。

ログサンプル

このトピックの例では、注文処理システムの JSON ログを使用します。JSON log sample

  • request フィールドには、JSON 形式の注文リクエスト情報が含まれています。リクエストには、あるユーザーの複数の注文を含めることができ、各注文には購入商品と支払い総額が含まれます。

  • response フィールドには、注文処理結果が含まれています。

    • リクエストが成功した場合、response フィールドの値は SUCCESS になります。

    • リクエストが失敗した場合、レスポンス フィールドの値は JSON 形式で、errcodemsg の情報が含まれます。

Logtail を使用して JSON モードでログを収集し、SLS に取り込んでクエリと分析を行えます。

インデックスの設定方法

ログデータをクエリまたは分析する前に、インデックスを設定する必要があります。JSON ログのインデックスを設定する際は、次の点を考慮してください。

インデックスタイプの選択方法

SLS は、フルテキストインデックスとフィールドインデックスをサポートしています。次の基準に基づいてインデックスタイプを選択します。詳細については、「インデックスの作成」をご参照ください。

  • すべてのフィールドをクエリするには、フルテキストインデックスを作成します。特定のフィールドのみをクエリする場合は、対象のフィールドにフィールドインデックスを作成することでコストを削減できます。

  • フィールドに対して SQL 分析を実行するには、そのフィールドのインデックスを作成し、統計を有効にする必要があります。

説明

フルテキストインデックスとフィールドインデックスの両方が設定されている場合、フィールドインデックスが設定されているフィールドでは、フィールドインデックスが優先されます。

たとえば、request フィールドと response フィールドを分析するには、それらのフィールドにインデックスを作成して統計を有効にすることができます。

インデックス設定におけるフィールドのデータ型の選択方法

インデックスを設定する際、フィールドのデータ型を text、long、double、または JSON に設定できます。詳細については、「データ型」をご参照ください。

JSON フィールドのデータ型を設定する際は、次の点を考慮してください。

  • フィールド値が標準の JSON 形式ではないが JSON コンテンツを含んでいる場合は、データ型を text に設定します。値が標準の JSON 形式である場合は、データ型を JSON に設定します。

    説明

    完全には有効ではない JSON ログの場合、SLS は有効な部分を解析できます。

  • データ型を JSON に設定した後、クエリを高速化するために JSON オブジェクト内のリーフノードのインデックスを作成できます。これには追加のインデックス作成料金が発生します。

  • SLS は JSON オブジェクト内のリーフノードのインデックスをサポートしていますが、リーフノードを含む子ノードのインデックスはサポートしていません。

  • SLS は、値が JSON 配列であるフィールド、または JSON 配列内のフィールドのインデックスをサポートしていません。

ログサンプルに基づいて、次のインデックスを作成できます。

  • request フィールド

    • request: 値は JSON 形式です。データ型を JSON に設定して、統計を有効にしてください。

    • request.clientIp: このフィールドは頻繁に分析されます。個別のインデックスを作成し、データ型を text に設定して、統計を有効にします。

    • request.http.path:このフィールドはまれにしか分析されないため、個別のインデックスを作成しないでください。 分析が必要な場合は、JSON 関数を使用して直接解析できます。

    • request.param:このフィールドはリーフノードを含む子ノードであり、インデックスを作成することはできません。

    • request.param.userId: このフィールドは頻繁に分析されます。個別のインデックスを作成し、データ型をtextに設定して統計を有効にします。

    • request.param.orders:値は JSON 配列です。このフィールドにはインデックスを作成できません。

  • response フィールド

    response フィールドの値は常に JSON 形式であるとは限らないため、データ型をテキストに設定し、統計を有効にしてください。

JSON log

インデックスを作成した後、新しく収集されたログは以下の図のように表示されます。JSON log

エイリアスの設定方法

JSON リーフノードのパスが長い場合は、エイリアスを設定できます。詳細については、「列のエイリアス」をご参照ください。JSON log

説明
  • フィールド名とエイリアスは、インデックス設定内のすべてのフィールドで一意である必要があります。

  • JSON タイプのフィールドでは、リーフノードの名前の一意性は、そのフルパスによって決定されます。たとえば、response フィールドのエイリアスを clientIp に設定した場合、システムは、このエイリアスを request.clientIp フィールド名の重複とはみなしません。

インデックス付き JSON フィールドのクエリと分析方法

クエリ・分析ステートメントは、query statement|analytic statement の形式を使用します。分析ステートメントでは、フィールド名を二重引用符 ("") で、文字列を一重引用符 ('') で囲みます。対象フィールドには、Key1.Key2.Key3 のようにフルパスを指定します。例: request.clientIp および request.param.userIdJSON ログのクエリと分析

たとえば、ユーザー 186499 のクライアント IP アドレスを検索するには、次の文を実行します。

*
and request.param.userId: 186499 |
SELECT
  distinct("request.clientIp")

クエリと分析の結果は次のとおりです。JSON log

JSON 関数の使用場面

複雑だが固定された JSON 構造を持ち、高いパフォーマンスが要求される大規模なデータセットの場合は、JSON リーフノードのフィールドインデックスを作成します。小規模なデータセットの場合は、フィールドインデックスなしで JSON 関数を使用してコストを節約できます。JSON 関数を使用すると、JSON ログを動的に処理および分析できます。場合によっては、クエリと分析に JSON 関数しか使用できないこともあります。

  • フィールド値が常に JSON 形式であるとは限らない場合や、前処理が必要な場合。

    例えば、response フィールドには、リクエストが失敗した場合にのみ errcode フィールドを含む JSON が含まれます。errcode の分布を分析するには、失敗したリクエストのログをフィルタリングし、JSON 関数を使用して errcode を抽出します。

    * not response:SUCCESS |
    SELECT
      json_extract_scalar(response, '$.errcode') AS errcode

    クエリと分析の結果は次のとおりです。JSON log

  • インデックス作成がサポートされていない JSON ノードでは、リアルタイム分析に JSON 関数のみを使用できます。例として、request.param フィールドや request.param.orders フィールドが挙げられます。

json_extract 関数と json_extract_scalar 関数の使い分け

json_extractjson_extract_scalar はどちらも JSON オブジェクトまたは配列からコンテンツを抽出します。主な違いは次のとおりです:

  • json_extractJSON 型を返し、json_extract_scalarvarchar 型を返します。

    説明

    これは SQL のデータ型 (varcharbigintbooleanJSONarraydate) を指し、SLS のインデックスデータ型とは異なります。SQL オブジェクトのデータ型を確認するには、typeof 関数を使用します。詳細については、「typeof 関数」をご参照ください。

  • json_extract は JSON オブジェクトの任意の下位構造を解析できます。json_extract_scalar はスカラー型 (文字列、ブール値、または数値) のリーフノードのみを解析し、対応する文字列を返します。

request フィールドから clientIp フィールドを抽出するには、いずれかの関数を使用できます。

  • json_extract を使用してデータを抽出します。

    * |
    SELECT
      json_extract(request, '$.clientIp')

    クエリと分析の結果は次のとおりです。

    JSON log

  • json_extract_scalar を使用してデータを抽出します。

    * | SELECT json_extract_scalar(request, '$.clientIp')

    クエリと分析の結果は次のとおりです。JSON log

clientIp の値の最初の部分を抽出するには、まず json_extract_scalar を使用して clientIp を抽出し、次に split_part を使用して最初の部分を抽出します。split_part は varchar 型の入力を必要とするため、ここでは json_extract を使用できません。

* |
SELECT
  split_part(
    json_extract_scalar(request, '$.clientIp'),
    '.',
    1
  ) AS segment

クエリと分析の結果は次のとおりです。JSON log

ほとんどの場合、json_extract_scalar を使用します。戻り値の型が varchar であり、他の関数と簡単に組み合わせることができるためです。JSON 構造自体を分析する場合は、json_extract を使用します。たとえば、リクエスト内の注文数 (request.param.orders JSON 配列の長さ) をカウントする場合などです。

* |
SELECT
  json_array_length((json_extract(request, '$.param.orders')))

クエリと分析の結果は次のとおりです。JSON log

重要

json_extract_scalarvarchar 型を返します。たとえば、上記の結果の数値 2 は varchar です。合計などの計算を実行するには、まず cast を使用して bigint に変換する必要があります。詳細については、「型変換関数」をご参照ください。

json_path の設定方法

json_extract などの関数を使用する場合、JSON パス を指定して、抽出する JSON オブジェクトの部分を指示します。フォーマットは $.a.b で、$ はルートノードを表し、ピリオド (.) は子ノードを参照します。

JSON フィールド名に http.pathhttp pathhttp-path などの特殊文字が含まれている場合は、ピリオドの代わりに角括弧 [] を使用し、フィールド名を二重引用符で囲みます。例: * |SELECT json_extract_scalar(request, '$["http.path"]')

説明

SDK を使用してクエリを実行する場合は、ダブルクォーテーションをエスケープしてください。 例: * | select json_extract_scalar(request, '$[\"http.path\"]')

JSON 配列から要素を抽出するには、ゼロベースのインデックスとともに角括弧 [] を使用します。例:

  • ユーザーの最初の注文の支払い額を表示します。

    * |
    SELECT
      json_extract_scalar(request, '$.param.orders[0].payment')

    クエリと分析の結果は次のとおりです。

    JSON log

  • ユーザーの最初の注文で購入された 2 番目の商品を表示します。

    * |
    SELECT
      json_extract_scalar(request, '$.param.orders[0].commodity[1]')

    クエリと分析の結果は次のとおりです。

    JSON log

JSON 配列の分析方法

JSON 配列を分析するには、castUNNEST 句を組み合わせて配列を展開し、その結果を集計します。

例 1

成功したすべての注文の合計支払い額を計算するには:

  1. 成功したリクエストをフィルタリングし、json_extract を使用して orders フィールドを抽出します。

    *
    and response: SUCCESS |
    SELECT
      json_extract(request, '$.param.orders')

    クエリと分析の結果は次のとおりです。

    JSON log

  2. JSON 配列を array(json) 型に変換します。

    *
    and response: SUCCESS |
    SELECT
      cast(
        json_extract(request, '$.param.orders') AS array(json)
      )

    クエリと分析の結果は次のとおりです。

    JSON log

  3. UNNEST を使用して配列を展開します。

    *
    and response: SUCCESS |
    SELECT
      orderinfo
    FROM  log,
      unnest(
        cast(
          json_extract(request, '$.param.orders') AS array(json)
        )
      ) AS t(orderinfo)

    クエリと分析の結果は次のとおりです。

    JSON log

  4. payment の値を json_extract_scalar で抽出し、bigint にキャストして合計します。

    *
    and response: SUCCESS |
    SELECT
      sum(
        cast(
          json_extract_scalar(orderinfo, '$.payment') AS bigint
        )
      )
    FROM  log,
      unnest(
        cast(
          json_extract(request, '$.param.orders') AS array(json)
        )
      ) AS t(orderinfo)

    クエリと分析の結果は次のとおりです。

    JSON log

例 2

成功したすべてのリクエストにおける各商品の数量をカウントするには、orders フィールドを抽出し、array(json) にキャストして UNNEST で展開します。各行が 1 つの注文を表します。次に、commodity フィールドを抽出し、再度キャストして展開します。各行が 1 つの商品を表します。最後に、グループ化してカウントします。

*
and response: SUCCESS |
SELECT
  item,
  count(1) AS cnt
FROM  (
    SELECT
      orderinfo
    FROM      log,
      unnest(
        cast(
          json_extract(request, '$.param.orders') AS array(json)
        )
      ) AS t(orderinfo)
  ),
  unnest(
    cast(
      json_extract(orderinfo, '$.commodity') AS array(json)
    )
  ) AS t(item)
GROUP  BY
  item
ORDER BY
  cnt DESC

クエリと分析の結果は次のとおりです。

JSON log