MongoDB 時間的資料欄位差異與優缺點

寫這一篇是想到了當年對於時間的設計,還特地回頭翻了以前寫的文章 MongoDB 使用、設計時間欄位小心得

又經過一年的磨練,對於之前的設計又有點想法想來聊聊。

起因

我們使用的語言是 .Net Core,設計的系統為跨國使用,因此時區問題是無法避免的。系統中一律使用 c# DateTimeOffset,直接存進 MongoDB 會變成一個陣列(可以參考上面的連結),在查詢上會變得緩慢。

下一步改動就跳到了 c# 的 UtcTick,這樣好處是儲存體都是 UTC 時間,對外溝通都一率使用 UTC,很符合我們的技術棧 gRPC (時間皆是用 timestamp)。很好的解決了當時的所有問題,反正客戶端在哪個時區,再進行轉換就好。

1
Timestamp 是 Unix 時間,`1970年1月1日00:00:00 UTC` 為時間原點

魔鬼藏在細節裡

使用一段時間後,發現我們有個小困境,有些使用者情境不需要如此精確的時間,例如可能只以小時或者天為單位,所幸儲存體不算貴,因此一種時間就有了三個欄位:

1
2
3
CreateTime (Ticks)
CreateTimeHr
CreateTimeDate

這樣還是能解決我們大部分的商務需求。但某一天接到一個臨時性的支援需求,需要以某個時間欄位以為單位進行統計資料(GroupBy),這時我驚覺,這個我們做不到了,況且今天是以週、雙週、月為單位呢?是不是要存更多欄位但又很少使用到,實在很浪費。

反思設計

回頭看 MongoDB 提供哪些時間的儲存資料類別:

Data Type PROS CONS
Date 精確度高 程式面需強制UTC
Timestamp 可無痛對外溝通 精確度不足
Long(Tick) 數值型別比較快 1. 人類無法閱讀 2.無法在 MongoDB 做轉換
Array(DateTimeOffset) 資料皆儲存到了
String(DateString) 別鬧了 別鬧了

透過上表,先來看看選手們:

  • Timestamp: 缺點就是精准度不夠啦!如果需求面沒有到毫秒,我應該是會考慮使用,且還是可以在 MongoDB 做轉換。
  • Long(Tick): 好,我必須承認這不是一個好的設計,很想獲得 Approve 進行整個系統大改進。Tick 除了無法閱讀,在查問題時需搭配網頁或工具貼來貼去的轉換,致命性問題就是無法調整精確度。
  • Date: 提供高精確度,且可以在 MongoDB 進行轉換,無疑是最全面的資料型別了,至於效能部分,目前還不敢說與 Long 的差異,也許未來有機會再來測試。
  • Array, String: 想都別想,真的。

結論

  • 有毫秒需求=> MongoDB 使用 Date
  • 無毫秒需求=>
    • 系統有使用 Timestamp => MongoDB 使用 Timestamp
    • 系統無使用 Timestamp => MongoDB 使用 Date

希望為後來設計新需求或是系統的人提供一點意見。