TDengine的降採樣查詢+跨時區統計

如果採集表中每5秒採集一個數據,但查詢時不想要這麼多,只想要1分鐘一個數據,這時面要用到降採樣查詢,如下面 interval(60s)表示60s一個數據,期間的數據要以取平均,最大,最小等

select _wstart, _wend, avg( current), min(current), max(current) from test.d100 where ts between '2017-07-14 10:40:01.000' and '2017-07-14 10:40:02.000' interval(1s);

//s秒,d天,m月,y年,w周

 

 

一文幫你掌握TDengine的降採樣查詢+跨時區統計 - 濤思數據TDengine - 博客園 (cnblogs.com)

作者:陳玉|濤思數據

小T導讀:作爲一款高性能的時序數據庫,TDengine提供了強大的數據分析功能。在TDengine官網的第一個章節裏,有這樣的描述:“無論是十年前還是一秒鐘前的數據,指定時間範圍即可查詢。數據可在時間軸上或多個設備上進行聚合。”

今天,我們的主角就是上文中“可在時間軸上”聚合的強大函數——INTERVAL。

INTERVAL是TDengine一大重要功能,可以幫助我們實現降低數據採集頻率的功能——也就是降採樣。舉個簡單的例子:假設我們有某個設備一年的數據,時間數據的頻率是1天,那麼就是一共365條數據。現在,如果我們想按照‘月’這個頻率統計,那麼數據量就變成了12條。

根據官網的語法描述,相關的功能模塊有三個:

  1. INTERVAL本身
  2. SLIDING
  3. INTERVAL OFFSET

對於以處理時序數據爲根基的時序數據庫來說,如何靈活的利用時間頻率來計算分析數據實在是太重要了。下面我們圍繞上面三個功能模塊,分別舉一個簡單的應用場景的例子並做出具體說明:

1. INTERVAL:查詢溫度傳感器t1記錄的溫度、壓力每五分鐘的平均值

select avg(t), avg(p) from t1 interval(5m);

這是一個最簡單的使用情況,INTERVAL負責指定時間範圍窗口,由AVG這種聚合函數來計算這個時間範圍內的平均值。也可以換成MAX/MIN這類的選擇函數,來統計出這個時間範圍內的最大值/最小值。(在TAOS SQL中,聚合函數指的是COUNT/AVG/TWA/SUM等用於從數據集中匯合再計算的函數,選擇函數是指 MIN/MAX/FIRST/LAST/LAST_ROW等用於從數據集中篩選結果的函數。)

INTERVAL本質上就是group by的時間版本,所以一定需要配合上述聚合或選擇函數來使用。INTERVAL後面的時間單位可以是 a(毫秒)、s(秒)、m(分)、h(小時)、d(自然日)、w(周), n(自然月) 和 y(自然年)。(暫時還不支持自然周,interval(1w) 目前等效於interval(7d))。

2. SLIDING:可以統計類似股票市場的均線

select avg(t) from stockmarket interval(5d) sliding(1d)。

上述語句的實際含義是統計股市上某股票所有每過一天的5天的價格平均值,把這些值連起來,就是大家熟知的五日均線了。

在上述計算過程中,SLIDING起到了非常關鍵的作用。我們已經知道,INTERVAL 的值負責指定每次執行查詢的時間窗口。SLIDING則代表着指定窗口向前滑動的時間。如下圖所示:

t0s,t1s,t2s分別是三個時間窗口的起點,t0e,t1e,t2e分別是三個時間窗口的終點。當我們在查詢中不指定SLIDING的值時,它默認等於INTERVAL VALUE。也即是說在第一個例子當中的select avg(t), avg(p) from t1 interval(5m)等效於select avg(t), avg(p) from t1 interval(5m) sliding (5m);

3. INTERVAL OFFSET:統計某個設備在其他時區(向西相差三個時區)的一個月的總數據量

select sum(t) from t1 interval(1n,3h) ;

這個SQL的語義是:統計當前服務端所在時區向西推動三個時區後的這個設備的該月總數據。OFFSET 3h代表的是OFFSET值爲3h,也就是說這個SQL適用於統計不同時區的自然月數據統計。

INTERVAL OFFSET會相對複雜一些。想了解的話,需要先更多地瞭解INTERVAL和時區的關係。

如果INTERVAL的值是自然日(d),自然月(n),自然年(y),那麼它就是對齊TDengine服務端所在時區的0點開始做的窗口切分,如下圖所示:不論當前所屬哪個時區,所有時間戳列的起始時間都是0點。

但是,如果是以時分秒及以下的時間單位去切分窗口,那麼INTERVAL的值則是對齊從UTC-0時間的00:00:00.000開始切分的時間窗口。

如下圖所示,時間戳列的起始時間都是8點,這是因爲TDengine客戶端的時區爲UTC-8,標準時間爲0點的時候,東八區爲8點(注意:在POSIX標準中,UTC-8代表東八區,與平時的習慣性表達不一樣)。

這個場景,就是官網文檔中這段話的含義:

TDengine 中時間戳的時區總是由客戶端進行處理,與服務端無關。具體來說,客戶端會對 SQL 語句中的時間戳進行時區轉換,轉爲 UTC-0時區的Unix時間戳再交由服務端進行寫入和查詢;在讀取數據時,服務端也是採用 UTC-0時區提供的原始數據,客戶端收到後再根據本地設置,把時間戳轉換爲本地系統所要求的時區進行顯示。

總結一下就是:TDengine以時間戳形式來存儲時間數據,時間戳本身是一個和時區無關的東西,但是由於TDengine要把數據查詢出來展示給世界上不同地區的用戶看,就和時區有關係了。在INTERVAL中,如果是自然日,自然月,自然年,均以TDengine服務端所在時區的0點爲起始時間進行時間窗口區分。如果是以h(小時)及以下爲單位切分窗口,那麼進行窗口切分的起始時間就是UTC時區的0點。

不論是哪個時區的客戶端,最終的計算列結果都是一致的,只是由於時區不同,所以顯示的時候在時間戳列上會有一些偏差。因此我們強烈建議,非特殊情況下,客戶端服務器和服務端服務器的時區要保持一致,從而使得兩邊的查詢顯示是一致的,從而減少不必要的誤解。

比如,左側客戶端count(*)看起來應該是1 4 2,實際上卻是4和3。這就是因爲兩邊時區不一致導致的視覺差異。這時候就要以服務端的顯示爲準:6月30日有4條數據,7月1日有3條數據——TDengine服務端所在服務器的查詢結果,永遠是所見即所得的正確。

搞清楚了INTERVAL對於自然日月年和時分秒的不同切分邏輯後,接下來,我們終於可以說一下OFFSET了。

OFFSET其實是INTERVAL功能的偏移值。通過調整OFFSET值,就可以在時間軸上自由選擇時間窗口的起始點。從而完成不同時區的數據分析統計。

比如,服務端當前的時區是東八區,但是我們想知道在東五區時區下,設備t1的每個月數據總量。就可以這樣寫:

select sum(t) from t1 interval(1n,3h) ;

但是由於OFFSET目前暫時不能支持負值,所以時間窗口的起點只能從時區東向西偏移。因此如果想用時區偏移功能統計24個時區,暫時可以把服務端所在的服務器時區設置爲東十二區(UTC-12)。

作爲一個定位國際化的產品,我們TDengine後面會繼續完善相關的功能。如果想了解更多更具體的細節,可以在GitHub上查看相關源代碼。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章