在很多場景下,數據并不是孤立的存在。例如股票價格的走勢,一天之內溫度的變化等。一組相關數據以時間為坐標串聯起來,形成一條連續的變化線,這就是時序數據。時序數據可以直觀地反映變化的規律性,也可以方便地用來識別和預測異常情形。
而時序數據庫,就是專門用來存儲時序數據的一類特殊數據庫。
相比于傳統的 RDBMS 或者 NoSQL,時序數據庫有下列鮮明的特征。
時序數據沒有復雜的結構和關聯。時序數據關注的是被測指標在時間維度上的變化規律,它并不需要復雜的嵌套的數據結構:時間戳連同數據值就構成了一個數據點。另外,時序數據也不關心不同的被測指標之間的關系(這種關系在定義良好的可視化圖表上一目了然),數據之間不需要任何諸如外鍵等關聯關系。
正是因為沒有復雜的結構和關聯,時序數據庫不需要提供范式和事務支持。時序數據庫面向的是與傳統數據庫截然不同的業務領域,范式和事務在其中是不必要的。不過,時序數據庫存在其他的限制和約束。
時序數據庫的實時寫入量通常很大。時序數據需要采集的數據量與數據源的數量以及采樣的時間精度成正比。在某些業務場景下,一秒鐘需要采集上萬甚至更多個數據點。
時序數據的結構
時序數據有著簡單的結構。
被測量的指標一般稱作 metric
。指標的一個孤立數據點表示為以指標名為索引的鍵值對:
metric -> (timestamp, value)
依時間順序逐次采集若干數據點,我們就得到了該被測量指標的一系列值:
metric -> (t0, v0), (t1, v1), (t2, v2), ...
這就是時序數據的基本結構,一般來說采樣的時間間隔是恒定的(記作 $\Delta t$,允許存在誤差)。作為示例,下面是一組溫度的時序數據。
temperature -> (1502433662000, 29.3), (1502433672002, 29.7), (1502433681999, 29.6), ...
僅僅依靠指標名稱來索引數據略嫌簡陋,有時候希望能對數據作出進一步的區分。為了達到這一目的,我們給指標添加一個或者多個標簽(labels)。例如,為了區分不同城市的溫度,我們引入一個叫做 city
的標簽。
temperature{city=beijing} -> ...
temperature{city=nanjing} -> ...
temperature{city=tianjin} -> ...
指標的名稱可以看作是一個叫作 name
的特殊標簽,這樣,數據的索引就一般化為了一組標簽的集合。
{name=temperature, city=beijing} -> ...
{name=temperature, city=nanjing} -> ...
{name=temperature, city=tianjin} -> ...
時序數據庫的讀寫特點
寫入操作的特點:
- 由于數據量龐大,存儲時需要引入某種壓縮方案。Facebook 在其闡述 Gorilla 數據庫的論文中介紹了一種非常適合時序數據庫的壓縮方案。
- 同樣由于數據量龐大,存儲時應當使用適當的留存策略(Retention Policy),定期刪除數據。一般采用三級存儲方案:最上層的內存用做緩存,存儲熱點數據;下一層的 SSD 用來存儲留存期(一般為數周或數月)之內的數據;此外還有一個數據中心用來保留全部數據。
- 寫入操作遠多于讀取操作,可能占到 99% 以上。絕大部分數據不會被用到。
- 數據總是追加式地寫入(順序寫入)。
- 數據寫入之后,就不會再被更新(無隨機更新)。
- 超出留存期的數據被整塊刪除(無隨機刪除)。
讀取操作的特點:
- 時序數據存在顯著的時間敏感性,越是近期的數據越重要。大部分讀取操作所請求的數據集中在最近一天或幾天。
- 對時序數據的分析過程中需要進行大量運算(求和、計算變化率等),時序數據庫需要高效地支持這些運算。
參考
你可以從以下兩篇文章中找到更多關于時序數據庫的討論:
另外,市面上已經有了很多時序數據庫,下面兩個列表提供了相關方面的內容:
- DB-Engines Ranking of Time Series DBMS
- [The complete list of all time series databases for your IoT project](The complete list of all time series databases for your IoT project)