MongoDB 使用、設計時間欄位小心得

結論:該使用什麼,沒有最正確,只有最適合。本篇文章選擇的方向,比較適合我在工作上遇到的情境,不見得看官也適用。

前提

冒險開始

很自然的,遇到時間,在C#階段我們會使用 DateTimeOffset,接著就很開心的存進 MongoDB。
打開MongoDB發現該欄位跟我們想得不太一樣,

alt

沒錯,DateTimeOffsetNow 變成一個陣列,裡面存的是 DateOffset,在sub document上加上 Index 絕對不是一件好事。

捨棄Offset!把它變成UTC DateTime格式吧!

哇~蒸蚌,這下欄位變成上圖的 DateTimeNow 欄位,沒有陣列了。
沒錯,這樣存進去就會變成只有一個欄位的 Date,但是這樣就夠了嗎?
經驗上這種時間格式一定都會拿來查詢條件,而查詢條件就是拿來比較的,介於~大小於這種,而這個比較的效率好嗎?肯定不會比數字來得好,就像比較字串效能還是輸給直接比較數字。

通通拿去轉Tick

下一階段的演進就是將所有的日期類別欄位都轉為Ticks,這樣做當然會有一些壞處,例如查問題或者找檔案的時候,都需要把這個時間再貼到轉換器上才能讀懂,但為了提升效能還是捏著下去做。

到這裡可能就差不多了吧?對於資料庫與Index略微了解的朋友,還想到了Index欄位上資料破碎程度帶來的影響,如果要比較的欄位是 1~1000的整數區間,如果你的使用情境只會在乎百位數,也就是 100、200、300等等,那在查詢欄位上的精確度需要這麼高嗎?
試想查詢的欄位是 153, 192, 221100, 100, 200 這樣建立索引後,索引的查詢哪個資料量較小?(Index scan count 在 MongoDB explain 會看得到)。

用空間換時間!

在這個硬碟空間不算太貴的年代,用一些儲存空間來換取服務執行效率是很划算的,於是不需要高度精確的某些日期欄位就會再額外儲存成 Date precision 的欄位,當然本身不需要這樣精確度,就直接改吧、別再額外儲存欄位。
於是我們的資料就變成類似這樣…

1
2
3
4
"
{"CreateTime","637572366980000000"} //21/05/2021 23:31:38
{"CreateTimeByDate","637571520000000000"} //21/05/2021 00:00:00
"

Index 就會建立在 CreateTimeByDate 欄位上,查詢也都是使用這個欄位,找到後再把 CreateTime 帶出來顯示等等。

後記

還是要強調,不是每個時間相關的欄位都需要這樣的設計,視需求而定,於是乎,BA與服務負責人的遠見就很重要了。
把時間做到這樣還有一個很大的好處,在之後的文章會再寫。

  • 作者: MingYi Chou
  • 版權聲明: 轉載不用問,但請註明出處!本網誌均採用 BY-NC-SA 許可協議。