日本熟妇hd丰满老熟妇,中文字幕一区二区三区在线不卡 ,亚洲成片在线观看,免费女同在线一区二区

查詢和分析JSON日志的常見問題

本文介紹查詢和分析JSON日志的常見問題。

日志樣例

本文中介紹的各個案例是基于如下JSON格式的訂單處理系統日志。JSON日志樣例

  • request字段為訂單請求信息,JSON格式。一個請求中包含一個用戶的多個訂單,訂單中包含購買的商品和支付總價。

  • response字段為訂單處理結果。

    • 請求成功時,response字段值為SUCCESS。

    • 請求失敗時,response字段值為JSON格式,包含errcode和msg信息。

您可以通過Logtail將該日志采集到日志服務中,進行查詢與分析。具體操作,請參見使用JSON模式采集日志

如何設置索引?

索引是一種存儲結構,用于對日志中的一列或多列進行排序。您只有設置索引后,才能進行查詢和分析操作。在為JSON日志設置索引時,可能涉及如下方面的問題。

如何選擇索引類型?

日志服務索引分為全文索引和字段索引,您可以參考如下說明,選擇索引類型。更多信息,請參見創建索引

  • 如果您需要查詢日志中的所有字段,建議創建全文索引;如果您明確僅查詢部分字段,可針對目標字段建立字段索引,減少索引費用。

  • 如果對字段有SQL分析需求,則必須對目標字段建立索引,并開啟統計功能。

說明

如果您同時配置了全文索引和字段索引,則配置了字段索引的字段,以字段索引的配置為準。

例如您要統計分析request字段和response字段,則需要創建這兩個字段的字段索引,并開啟統計功能。

在索引配置中,如何選擇字段的數據類型?

在設置索引時,字段的數據類型分為text、long、double和JSON。更多信息,請參見數據類型

當您設置JSON字段的數據類型時,可參考如下思路。

  • 如果字段值不是標準JSON格式,可能只是包含了JSON格式的內容,則設置為text類型;如果字段值是標準JSON格式,則設置為JSON類型。

    說明

    針對非完全合法的JSON日志,日志服務支持解析合法部分。

  • 將某個字段設置為JSON類型后,如果對JSON對象中的某個葉子節點有進一步的分析需求,可以為葉子節點建立索引,這樣可以加快葉子節點的查詢和分析速度,但同時也會產生額外的索引費用。

  • 日志服務支持JSON對象中的葉子節點建立索引,但不支持包含葉子節點的子節點建立索引。

  • 日志服務不支持值為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格式,因此設置為text類型,并開啟統計功能。

JSON日志

創建索引后,新采集的日志將顯示為如下格式。JSON日志

如何設置別名?

JSON葉子節點的路徑較長,您可以為其設置別名。更多信息,請參見列的別名JSON日志

說明
  • 在設置索引時,不同字段的字段名或別名不能重復。

  • 對于JSON類型的字段,JSON葉子節點的名稱是按照全路徑進行重名判定的。例如為response字段設置別名為clientIp,系統不會判定該別名與request.clientIp字段名重復。

如何查詢和分析有索引的JSON字段?

查詢和分析語句格式為查詢語句|分析語句。在分析語句中,您必須使用雙引號("")包裹字段名稱,使用單引號('')包裹字符串。您還需為目標字段加上所有的父路徑,格式為Key1.Key2.Key3。例如request.clientIprequest.param.userId。更多信息,請參見查詢和分析JSON日志

例如統計186499用戶的客戶端IP地址,可執行如下語句。

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

查詢和分析結果如下所示。JSON日志

何時使用JSON函數?

首先,在查詢和分析JSON日志時,如果數據量很大或結構復雜但相對固定,并且您對查詢分析性能有要求時,建議對JSON葉子節點建立字段索引,然后再進行查詢分析。如果數據量比較小,出于成本考慮,您可以不對JSON葉子節點建立字段索引,而是使用JSON函數進行查詢和分析。使用JSON函數,可以靈活地對JSON日志進行動態處理和分析。另外,針對一些特殊情況,只能使用JSON函數進行查詢與分析。

  • 字段值不一定是JSON格式或者需要先進行一些預處理。

    例如response字段,只有在請求失敗時是JSON格式,并且包含errcode字段。那么您要分析errcode的分布情況,則需先使用查詢語句過濾出請求失敗的日志,然后在分析語句中使用JSON函數動態提取errcode字段值。

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

    查詢和分析結果如下所示。JSON日志

  • 不支持建立索引的JSON節點,只能使用JSON函數實時分析。例如request.param字段和request.param.orders字段。

如何選擇json_extract函數和json_extract_scalar函數?

json_extract函數和json_extract_scalar函數都是用于從JSON對象或JSON數組中提取內容,用法類似,主要區別如下:

  • json_extract函數的返回值是JSON類型,json_extract_scalar函數的返回值是varchar類型。

    說明

    此類型是指SQL語法中的數據類型,例如varchar、bigint、boolean、JSON、array、date等,與日志服務索引中的數據類型不同。您可以通過typeof函數查看SQL分析對象的數據類型。更多信息,請參見typeof函數

  • json_extract函數可以解析JSON對象中任意一塊子結構,json_extract_scalar函數只解析標量類型(字符串、布爾值或者整型值)的葉子節點,返回對應的字符串。

例如提取request字段中的clientIp字段,兩個函數都支持。

  • 使用json_extract函數進行提取。

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

    查詢和分析結果如下所示。

    JSON日志

  • 使用json_extract_scalar函數進行提取。

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

    查詢和分析結果如下所示。JSON日志

在上述基礎上,如果要提取clientIp字段值中的第一部分,您需要先使用json_extract_scalar函數提取clientIp的值,然后使用split_part函數提取IP地址中的第一個數字。此處不支持使用json_extract函數,因為split_part函數的入參需為varchar類型。

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

查詢和分析結果如下所示。JSON日志

一般情況下,如果您需要從JSON對象中提取字段進行分析,直接使用json_extract_scalar函數即可。因為json_extract_scalar函數的返回值為varchar類型,便于與其他函數結合使用。但是當您需要對JSON結構本身進行分析時,需要使用json_extract函數。例如您要統計一次請求中的訂單數,即統計request.param.orders字段中JSON數組的長度,可使用如下查詢分析語句。

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

查詢和分析結果如下所示。JSON日志

重要

json_extract_scalar函數的返回值是varchar類型。例如您上述示例中的數值2,其數據類型也是varchar類型,如果您要對該值進行求和等計算,需要先使用cast函數,將其轉換為bigint類型。更多信息,請參見類型轉換函數

如何設置json_path?

使用json_extract等函數從JSON日志中提取字段時,您需指定json_path,用于標明需要提取JSON對象中的哪一部分。json_path格式為$.a.b,美元符號($)代表當前JSON對象的根節點,然后通過半角句號(.)引用到待提取的節點。

如果JSON對象的字段中存在特殊字符(例如http.path字段、http path字段、http-path字段等),則需要使用中括號[]代替半角句號(.),然后使用雙引號("")包裹字段名,例如* |SELECT json_extract_scalar(request, '$["http.path"]')

說明

如果是通過SDK進行查詢和分析,則需要對雙引號("")進行轉義,例如* | select json_extract_scalar(request, '$[\"http.path\"]')

提取JSON數組中的某個元素時,可以用中括號[]。在中括號中,通過數字來表示下標,下標從0開始。例如:

  • 查看用戶第一個訂單的金額。

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

    查詢和分析結果如下所示。

    JSON日志

  • 查看用戶第一個訂單中購買的第二件商品。

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

    查詢和分析結果如下所示。

    JSON日志

如何分析JSON數組?

當日志中有JSON數組時,您可以結合cast函數和UNNEST子句,展開JSON數組,再進行聚合統計。

示例1

例如您要統計所有請求成功的訂單的金額,可參見如下思路。

  1. 使用查詢語句過濾出請求成功的日志,然后在分析語句中使用json_extract函數提取出orders字段的值。

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

    查詢和分析結果如下所示。

    JSON日志

  2. 將上述提取的JSON數組(JSON類型)轉換為array類型。

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

    查詢和分析結果如下所示。

    JSON日志

  3. 使用UNNEST子句將數組展開。

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

    查詢和分析結果如下所示。

    JSON日志

  4. 使用json_extract_scalar提取payment字段值,再使用cast函數將其轉換為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日志

示例2

統計所有成功的請求中,每一種商品被購買的數量。您可以先提取order字段,將其轉換為array(json)類型,再使用UNNEST語句將其展開,展開結果中的每一行代表一個訂單。然后使用json_extract函數提取commodity字段,將其轉換為array(json)類型,再使用UNNEST語句將其展開,展開結果中的每一行代表一個商品。最后再進行分組求和。具體思路請參見示例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日志