1. 程式人生 > >數據聚合(一)

數據聚合(一)

ref 過去的 div 觀測 ive -a 由於 默認 會有

在統計學中,聚合的定義指

使用基於多組觀測結果的總結的統計替換多組觀測結果 -- 來自 https://web.archive.org/web/20120112062156/http://www.r-bloggers.com/aggregation-and-restructuring-data-from-%E2%80%9Cr-in-action%E2%80%9D/

預期的功能及實現

實現一個由分鐘到年的聚合系統。

一、根據下一級數據聚合

比如小時的數據由分鐘聚合,天的數據由小時聚合,周、月的數據由天聚合,年的數據由月聚合。

要求:

  • 下級數據存在
  • 選擇正確的下級數據。比如月數據就不能由周數據聚合,而只能從天來聚合。

好處:
可以減少計算量。

二、數據完整

由於要根據下一級數據聚合,所以每個級別的數據都不能少。所以需要

  • 能夠檢測(各個級別的)數據完整
  • 能夠冪等地重跑數據
  • 自動檢測到數據不完整後,能自動地重跑數據

時區問題

一般的聚合都是基於時間的,比如從分鐘以下聚合為分鐘,然後小時,天,周,月,年等,所以就會有時區存在。

寫入與查詢

寫入數據庫的時間要帶上時區。因為 MySQL、MongoDB 等數據庫會將寫入的 datetime 轉化為 UTC 時區再儲存,所以如果寫入的時間沒有帶時區,數據庫就會認為寫入時間是 UTC 時區,可能會與你預期的不一致。

同理,查詢時也要帶上時區,因為數據庫默認沒有時區的時間為 UTC 時區。

聚合結果的時間儲存

由於當前級別的數據是根據下一級數據聚合的,所以需要儲存級別--時間類型以及時間。

時間類型為

  1. minutely
  2. hourly
  3. daily
  4. weekly
  5. monthly
  6. yearly

聚合時間為時間段的起點,我們把它叫做 time_start

"date_type" : "minutely", "time_start" : ISODate("2018-01-21T05:01:00Z")
"date_type" : "minutely", "time_start" : ISODate("2018-01-21T05:02:00Z")
...
"date_type" : "minutely", "time_start" : ISODate("2018-01-21T05:59:00Z")
// 根據以上的分鐘數據聚合小時數據
"date_type" : "hourly", "time_start" : ISODate("2018-01-21T05:00:00Z")

多時區

由於在不同時區的每天的定義是不同的:

北京時間 07月31日為 “07月30日16:00:00 UTC -- 07月31日16:00:00 UTC” 而東京則為 “07月30日15:00:00 UTC -- 07月31日15:00:00 UTC”。

我目前的想法是再給聚合加上時區參數,但在本文不討論聚合包含多時區問題,因為能用到的地方比較少。

聚合時機

聚合時機為當下一級別的數據不再變化時。一般來說,過去的數據是不會再變化的,所以我們聚合過去的數據:當前分鐘聚合上一分鐘的數據,當前小時聚合上一小時的數據,每月一號計算上一月的數據。

如果存在特殊情況導致要等待的久一些:比如由於網絡延遲導致數據來的慢一些。我們也要進行調整:比如當前分鐘聚合5分鐘前的數據。

數據聚合(一)