數據聚合(一)
在統計學中,聚合的定義指
使用基於多組觀測結果的總結的統計替換多組觀測結果 -- 來自 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 時區。
聚合結果的時間儲存
由於當前級別的數據是根據下一級數據聚合的,所以需要儲存級別--時間類型以及時間。
時間類型為
- minutely
- hourly
- daily
- weekly
- monthly
- 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分鐘前的數據。
數據聚合(一)