1. 程式人生 > >MongoDB資料建模小案例:物聯網時序資料庫建模

MongoDB資料建模小案例:物聯網時序資料庫建模

注:本案例來自MongoDB官方教程PPT,也是一個非常典型的CASE,故此翻譯,並結合當前MongoDB版本做了一些內容上的更新。

本案例非常適合與IoT場景的資料採集,結合MongoDB的Sharding能力,文件資料結構等優點,可以非常好的解決物聯網使用場景。

需求

案例背景是來自真實的業務,美國州際公路的流量統計。資料庫需要提供的能力:

  • 儲存事件資料
  • 提供分析查詢能力
  • 理想的平衡點:

    • 記憶體使用
    • 寫入效能
    • 讀取分析效能
  • 可以部署在常見的硬體平臺上

幾種建模方式

每個事件用一個獨立的文件儲存

{
    segId: "I80_mile23",
    speed: 63,
    ts: ISODate
("2013-10-16T22:07:38.000-0500") }
  • 非常“傳統”的設計思路,每個事件都會寫入一條同樣的資訊。多少的資訊,就有多少條資料,資料量增長非常快。
  • 資料採集操作全部是Insert語句;

每分鐘的資訊用一個獨立的文件儲存(儲存平均值)

{
    segId: "I80_mile23",
    speed_num: 18,
    speed_sum: 1134,
    ts: ISODate("2013-10-16T22:07:00.000-0500")
}
  • 對每分鐘的平均速度計算非常友好(speed_sum/speed_num);
  • 資料採集操作基本是Update語句;
  • 資料精度降為一分鐘;

每分鐘的資訊用一個獨立的文件儲存(秒級記錄)

{
    segId: "I80_mile23",
    speed: {0:63, 1:58, ... , 58:66, 59:64},
    ts: ISODate("2013-10-16T22:07:00.000-0500")
}
  • 每秒的資料都儲存在一個文件中;
  • 資料採集操作基本是Update語句;

每小時的資訊用一個獨立的文件儲存(秒級記錄)

{
    segId: "I80_mile23",
    speed: {0:63, 1:58, ... , 3598:54, 3599:55},
    ts: ISODate("2013-10-16T22:00:00.000-0500")
}

相比上面的方案更進一步,從分鐘到小時:

  • 每小時的資料都儲存在一個文件中;
  • 資料採集操作基本是Update語句;
  • 更新最後一個時間點(第3599秒),需要3599次迭代(雖然是在同一個文件中)

進一步優化下:

{
    segId: "I80_mile23",
    speed: {
        0:  {0:47, ..., 59:45},
        ...,
        59: {0:65, ... , 59:56}
    }
    ts: ISODate("2013-10-16T22:00:00.000-0500")
}
  • 用了巢狀的手法把秒級別的資料儲存在小時資料裡;
  • 資料採集操作基本是Update語句;
  • 更新最後一個時間點(第3599秒),需要59+59次迭代;

巢狀結構正是MongoDB的魅力所在,稍動腦筋把一維拆成二維,大幅度減少了迭代次數;

每個事件用一個獨立的文件儲存VS每分鐘的資訊用一個獨立的文件儲存

從寫入上看:後者每次修改的資料量要小很多,並且在WiredTiger引擎下,同一個文件的修改一定時間視窗下是可以在記憶體中合併的;
從讀取上看:查詢一個小時的資料,前者需要返回3600個文件,而後者只需要返回60個文件,效率上的差異顯而易見;
從索引上看:同樣,因為穩定數量的大幅度減少,索引尺寸也是同比例降低的,並且segId,ts這樣的冗餘資料也會減少冗餘。容量的降低意味著記憶體命中率的上升,也就是效能的提高;

每小時的資訊用一個獨立的文件儲存VS每分鐘的資訊用一個獨立的文件儲存

從寫入上看:因為WiredTiger是每分鐘進行一次刷盤,所以每小時一個文件的方案,在這一個小時內要被反覆的load到PageCache中,再刷盤;所以,綜合來看後者相對更合理;
從讀取上看:前者的資料資訊量較大,正常的業務請求未必需要這麼多的資料,有很大一部分是浪費的;
從索引上看:前者的索引更小,記憶體利用率更高;

總結

那麼到底選擇哪個方案更合理呢?從理論分析上可以看出,不管是小時儲存,還是分鐘儲存,都是利用了MongoDB的資訊聚合的能力。

  • 每小時的資訊用一個獨立的文件儲存:設計上較極端,優勢劣勢都很明顯;
  • 每分鐘的資訊用一個獨立的文件儲存:設計上較平衡,不會與業務期望偏差較大;

落實到現實的業務上,哪種是最優的?最好的解決方案就是根據自己的業務情況進行效能測試,以上的分析只是“理論”基礎,給出“實踐”的方向,但千萬不可以此論斷。

VS InfluxDB

說到時序儲存需求,大家一定還會想到非常厲害的InfluxDB,InfluxDB針對時序資料做了很多特定的優化,但MongoDB採用聚合設計模式同樣也可以大幅度較少資料尺寸。根據最新的測試報告,讀取效能基本相當,壓縮能力上InfluxDB領先MongoDB。但MongoDB的優勢在於可以儲存更豐富的資訊,比如地理座標,文字描述等等其他屬性,業務場景上支援更廣泛。

另外,MongoDB的Sharding水平擴充套件能力,Aggragation功能,Spark Connector等等特性,對IoT來說,生態優勢明顯。

原文地址:https://yq.aliyun.com/articles/66477?spm=5176.100239.blogcont73664.27.h8eZaz