2010-11-09 74 views
2

我有一個設備,我正在輪詢很多不同的字段,每x毫秒 設備返回一個我需要存儲的id和值列表時間戳在一個數據庫中。在數據庫中組織大量時間戳值(sql/nosql)

系統的用戶需要能夠查詢此數據庫中的歷史日誌以創建圖表或查詢每個值的上次時間戳。

一個簡單的方法是定義一個MySQL表

id,value_id,timestamp,value 

,並讓用戶選擇

Select value form t where value_id=x order by timestamp desc limit 1 

,只是推動一切有與時間戳和id的索引,但我的問題是什麼設計模式的最佳方法是性能/規模?或使用nosql?任何人都可以評論可能的設計權衡。這樣的設計是否會有數百萬條記錄?

回答

1

當你說「...或查詢每個值的最後一個時間戳」時,你是在想什麼?

select max(timestamp) from T where value = ? 

如果你有幾百萬的記錄,上面是你的意思(即值僅在WHERE子句中),那麼你需要的值列的索引,否則你不得不做一個全表掃描。但是,如果查詢總是在WHERE子句中有[timestamp]列,那麼如果在時間戳上有索引,則不需要[value]列上的索引。

您需要在時間戳列的索引,如果您的用戶將發佈在時間戳列單獨出現在WHERE子句中查詢:

select * from T where timestamp > x and timestamp < y 

你可以索引的所有三個列,但要確保寫入不會因索引開銷而減慢。

當你有一個非常大的數據庫時,經驗法則是每個查詢都應該能夠使用索引,這樣就可以避免全表掃描。

編輯:

在您的澄清後添加一些額外的評論。

我想知道你將如何知道id? [id]也許是產品代碼?

如果沒有很多不同的產品代碼,也就是說它是低基數索引,那麼對於id的單個簡單索引可能無法很好地擴展。樹的再平衡可能會減慢每x毫秒發生的批量插入。 (id,timestamp)上的複合索引會比簡單索引好。

如果您很少需要對多個產品進行排序,但通常是基於單個產品代碼進行選擇,那麼使用散列鍵稀疏表而非B樹的非傳統DBMS可能會非常甚至可以爲您提供更好的選擇。在這樣的數據庫中,給定密鑰的所有記錄都可以在同一組連續的「頁面」上物理找到;哈希算法將查找關鍵字並返回記錄所在的頁碼。由於沒有索引,因此不需要重新平衡索引,因此您完全避免了相關的擴展問題。然而,儘管散列文件數據庫在基於鍵值的低開銷幾乎即時檢索方面表現優異,但它們在對屬性上的大型記錄組進行排序時往往效果不佳,因爲數據不是以物理方式存儲在任何有意義的順序和收集記錄可能涉及很多顛簸。在你的情況下,時間戳將是該屬性。如果我在你的鞋子裏,我會根據id的基數決定我的決定:在一百萬條記錄的數據集中,會發現多少個DISTINCT ID?

又一EDIT,因爲該網站IS不是讓我添加另一個解答:

簡單的方法是具有兩個表,一個與正在進行的歷史,它總是具有新值的插入,而另一隻含250個記錄,每個部分一個,其中最新值覆蓋/替換前一個值。

Update latest 
set value = x 
where id = ? 
+0

我正在選擇id並需要獲取該值,添加了關於選擇如何工作的思路 – kokoko 2010-11-09 11:45:02

+0

約有250個DISTINCT IDS – kokoko 2010-11-09 21:32:31

1

你的

  • 指數(複合材料;覆蓋value_id,時間戳和值,或二者的某種結合)一個選擇:你應該測試不同的索引的性能;複合和非複合,也要注意有很多不同的方法來獲得'最大每個組'(搜索,所以特別是帶變量的mysql版本)

  • 觸發器 - 您可能使用觸發器來維護最大行在另一個表中的值(最佳性能的進一步選擇;這是多餘的,可以保存在內存中)

  • 懶惰統計/觸發器,因爲你的數據庫經常更新,如果你定期更新你的統計信息,您可以允許統計數據爲y秒,如果您每秒輪詢1000次/ x次,那麼您可能會節省y * 100/x個潛在更新;這可能是顯而易見的,尤其是在可擴展性方面)

以上情況屬實,如果您正在尋找性能的最後一點,如果不是簡單的話。

+0

您是否需要維護每個零件的取代值的歷史記錄?還是你真的只對最近的價值感興趣?我已經更新了我的答案,以展示如何能夠非常有效地完成這兩項任務。 – Tim 2010-11-09 21:47:06

+0

我需要兩個,謝謝你的偉大答案! – kokoko 2010-11-09 22:09:25

+0

你是什麼意思的「搜索,特別是與變量的mysql版本」? – kokoko 2010-11-09 22:15:54