時間序列分析

雲端服務和IoT裝置會產生遙測數據,可用來取得見解,例如監視服務健康情況、實體生產程式和使用量趨勢。 相較於一般基準模式,執行時間序列分析是識別這些計量模式模式中偏差的一種方式。

Kusto 查詢語言 (KQL) 包含建立、操作和分析多個時間序列的原生支援。 在本文中,瞭解如何使用 KQL 來建立和分析數千個時間序列,以秒為單位,並啟用近乎即時的監視解決方案和工作流程。

建立時間序列

在本節中,我們將使用 make-series 運算子,以簡單且直覺的方式建立大量的標準時間序列,並視需要填入遺漏的值。 時間序列分析中的第一個步驟是分割原始遙測資料表並轉換為一組時間序列。 此資料表通常會包含一個時間戳記資料行、內容相關的維度,以及選擇性計量。 維度可用來分割資料。 目標是依規律的時間間隔,為每個分割區建立數千個時間序列。

輸入資料表 demo_make_series1 會包含 60 萬筆任意 Web 服務流量的記錄。 使用下列命令來取樣 10 筆記錄:

demo_make_series1 | take 10 

結果資料表會包含一個時間戳記資料行、三個內容相關的維度資料行,但沒有任何計量:

TimeStamp BrowserVer OsVer 國家/地區
2016-08-25 09:12:35.4020000 Chrome 51.0 Windows 7 英國
2016-08-25 09:12:41.1120000 Chrome 52.0 Windows 10
2016-08-25 09:12:46.2300000 Chrome 52.0 Windows 7 英國
2016-08-25 09:12:46.5100000 Chrome 52.0 Windows 10 英國
2016-08-25 09:12:46.5570000 Chrome 52.0 Windows 10 立陶宛共和國
2016-08-25 09:12:47.0470000 Chrome 52.0 Windows 8.1 印度
2016-08-25 09:12:51.3600000 Chrome 52.0 Windows 10 英國
2016-08-25 09:12:51.6930000 Chrome 52.0 Windows 7 荷蘭
2016-08-25 09:12:56.4240000 Chrome 52.0 Windows 10 英國
2016-08-25 09:13:08.7230000 Chrome 52.0 Windows 10 印度

由於沒有計量,因此,我們僅能建置一組代表流量計數本身的時間序列,其會使用下列查詢依 OS 進行分割:

let min_t = toscalar(demo_make_series1 | summarize min(TimeStamp));
let max_t = toscalar(demo_make_series1 | summarize max(TimeStamp));
demo_make_series1
| make-series num=count() default=0 on TimeStamp from min_t to max_t step 1h by OsVer
| render timechart 
  • 使用 make-series 運算子來建立含三個時間序列的集合,其中:
  • 實際的時間序列資料結構是每個時間間隔中彙總值的數值陣列。 我們使用 render timechart 來產生視覺效果。

在上述資料表中,我們有三個分割區。 我們可以針對每個 OS 版本建立個別的時間序列:Windows 10 (紅色)、7 (藍色) 和 8.1 (綠色),如下圖所示:

時間序列數據分割。

時間序列分析函式

在本節中,我們將執行一般序列處理函式。 建立一組時間序列之後,KQL 支援不斷成長的函式清單來處理和分析它們。 我們將描述一些代表性函式來處理和分析時間序列。

篩選

篩選是單一處理中的常見做法,非常適合用於時間序列處理工作 (例如,緩和吵雜的訊號、變更偵測)。

  • 有兩個泛型篩選函式:
    • series_fir():套用 FIR 篩選。 用於移動時間序列平均和差異的簡單計算,以進行變更偵測。
    • series_iir():套用 IIR 篩選。 用於指數平滑和累計總和。
  • Extend 時間序列,此時間序列會透過在查詢中新增大小 5 個間隔的新移動平均序列 (名為 ma_num) 來設定:
let min_t = toscalar(demo_make_series1 | summarize min(TimeStamp));
let max_t = toscalar(demo_make_series1 | summarize max(TimeStamp));
demo_make_series1
| make-series num=count() default=0 on TimeStamp from min_t to max_t step 1h by OsVer
| extend ma_num=series_fir(num, repeat(1, 5), true, true)
| render timechart

時間序列篩選。

迴歸分析

Azure Data Explorer 支援分段線性回歸分析,以估計時間序列的趨勢。

  • 使用 series_fit_line() \(英文\),以使最佳線條擬合至某個時間序列以進行一般趨勢偵測。
  • 使用 series_fit_2lines \(英文\) 來偵測趨勢變更 (相對於基準線),這類變更對於監視案例非常實用。

series_fit_line()時間序列查詢中的 和 series_fit_2lines() 函式範例:

demo_series2
| extend series_fit_2lines(y), series_fit_line(y)
| render linechart with(xcolumn=x)

時間序列回歸。

  • 藍色:原始時間序列
  • 綠色:擬合線
  • 紅色:兩條擬合線

注意

此函式已準確地偵測到跳轉 (層級變更) 點。

季節性偵測

許多計量都會遵循季節性 (週期) 模式。 雲端服務的使用者流量通常會包含每日和每週模式,這類模式在工作日中間最高,在夜晚和週末則最低。 IoT 感應器會定期測量。 實際度量 (例如溫度、壓力或溼度) 可能也會顯示季節性行為。

下列範例會在 Web 服務的一個月流量 (以 2 小時為間隔) 上套用季節性偵測:

demo_series3
| render timechart 

時間序列季節性。

注意

如果特定的相異期間不存在,則為異常狀況

demo_series3
| project (periods, scores) = series_periods_detect(num, 0., 14d/2h, 2) //to detect the periods in the time series
| mv-expand periods, scores
| extend days=2h*todouble(periods)/1d
週期 分數 days
84 0.820622786055595 7
12 0.764601405803502 1

此函式會偵測每日和每週的季節性。 每日分數會低於每週分數,因為週末與工作日不同。

元素型函式

您可以針對時間序列進行算術和邏輯運算。 我們可以使用 series_subtract() \(英文\) 來計算剩餘的時間序列,即原始未經處理的計量和經過平滑處理之時間序列間的差異,並尋找剩餘訊號中的異常狀況:

let min_t = toscalar(demo_make_series1 | summarize min(TimeStamp));
let max_t = toscalar(demo_make_series1 | summarize max(TimeStamp));
demo_make_series1
| make-series num=count() default=0 on TimeStamp in from min_t to max_t step 1h by OsVer
| extend ma_num=series_fir(num, repeat(1, 5), true, true)
| extend residual_num=series_subtract(num, ma_num) //to calculate residual time series
| where OsVer == "Windows 10"   // filter on Win 10 to visualize a cleaner chart 
| render timechart

時間序列作業。

  • 藍色:原始時間序列
  • 紅色:平滑時間序列
  • 綠色:剩餘時間序列

大規模的時間序列工作流程

下列範例示範這些函式如何在數千個時間序列上大規模執行 (以秒為單位) 以進行異常偵測。 若要查看四天中 DB 服務讀取計數計量的一些範例遙測記錄,請執行下列查詢:

demo_many_series1
| take 4 
timestamp Loc Op DB DataRead
2016-09-11 21:00:00.0000000 Loc 9 5117853934049630089 262 0
2016-09-11 21:00:00.0000000 Loc 9 5117853934049630089 241 0
2016-09-11 21:00:00.0000000 Loc 9 -865998331941149874 262 279862
2016-09-11 21:00:00.0000000 Loc 9 371921734563783410 255 0

以及簡單的統計資料:

demo_many_series1
| summarize num=count(), min_t=min(TIMESTAMP), max_t=max(TIMESTAMP) 
num min_t max_t
2177472 2016-09-08 00:00:00.0000000 2016-09-11 23:00:00.0000000

以 1 小時的讀取計量間隔來建置時間序列 (總共四天 * 24 小時 = 96 點),會產生標準模式波動:

let min_t = toscalar(demo_many_series1 | summarize min(TIMESTAMP));  
let max_t = toscalar(demo_many_series1 | summarize max(TIMESTAMP));  
demo_many_series1
| make-series reads=avg(DataRead) on TIMESTAMP from min_t to max_t step 1h
| render timechart with(ymin=0) 

大規模時間序列。

上述行為會讓人產生誤解,因為單一的一般時間序列會彙總自數千個可能具有異常模式的不同執行個體。 因此,我們會針對每個執行個體建立一個時間序列。 實例是由 Loc (位置) 、Op (作業) 和 DB (特定電腦) 所定義。

我們可以建立多少個時間序列?

demo_many_series1
| summarize by Loc, Op, DB
| count
計數
18339

現在,我們將建立一組 18339 個讀取計數計量的時間序列。 我們會將 by 子句新增至 make-series 陳述式、套用線性迴歸,然後選取前兩個趨勢下降最明顯的時間序列:

let min_t = toscalar(demo_many_series1 | summarize min(TIMESTAMP));  
let max_t = toscalar(demo_many_series1 | summarize max(TIMESTAMP));  
demo_many_series1
| make-series reads=avg(DataRead) on TIMESTAMP from min_t to max_t step 1h by Loc, Op, DB
| extend (rsquare, slope) = series_fit_line(reads)
| top 2 by slope asc 
| render timechart with(title='Service Traffic Outage for 2 instances (out of 18339)')

時間序列前兩個。

顯示執行個體:

let min_t = toscalar(demo_many_series1 | summarize min(TIMESTAMP));  
let max_t = toscalar(demo_many_series1 | summarize max(TIMESTAMP));  
demo_many_series1
| make-series reads=avg(DataRead) on TIMESTAMP from min_t to max_t step 1h by Loc, Op, DB
| extend (rsquare, slope) = series_fit_line(reads)
| top 2 by slope asc
| project Loc, Op, DB, slope 
Loc Op DB slope
Loc 15 37 1151 -102743.910227889
Loc 13 37 1249 -86303.2334644601

在不到兩分鐘內,已分析接近 20,000 個時間序列,並偵測到讀取計數突然下降的兩個異常時間序列。

這些與快速效能結合的進階功能提供獨特的強大解決方案,以供時間序列分析使用。