2012-12-06 84 views
3

我想正確設計我的數據庫。也許有人可以幫助我。需要正確的數據庫結構來減小大小

我有圍繞寫入100個鍵/值每3秒的表的裝置。 有人建議將其存儲這樣的:

^^時間戳key1的^^KEY 2 [...]^^ key150

| 12/06/12 | null | 2243466 | [...]空^

但我認爲是完全錯誤的,而不是動態的。因爲我可以有很多空值。 於是,我就盡我所能,並設計它,我怎麼在學校學過: http://ondras.zarovi.cz/sql/demo/?keyword=tempidi

這裏是我寫的每一個值100values內,這意味着這將是始終不變的,併產生大量的時間戳問題數據的。

可能有人給我一個暗示如何降低數據庫的大小?我基本上糾正了我的企業風險管理?

+3

您是否關注通過將相同的時間戳寫入100行所使用的磁盤空間? –

+0

是的。 我的計算是: 100值* 16bytes * 24(h)* 60(min)* 60(s)* 30(month)= 3.8GB /月 –

+0

無論誰建議像這樣存儲不應該推薦數據庫楷模。 – Kermit

回答

0

如果你要必須在MySQL中實現一個鍵值存儲,那麼使它比這更復雜沒有任何意義。

create table key_value_store (
    run_time datetime not null, 
    key_name varchar(15) not null, 
    key_value varchar(15) not null, 
    primary key (run_time, key_name) 
); 

如果你的關鍵字和值兩者的平均長度爲10字節,你看約86萬行,每月2.5GB,你不需要任何連接。如果所有值(列key_value)都是整數或浮點數,則可以更改數據類型並減少一點空間。

一個與SQL實現鍵值存儲的主要問題是,除非所有值都相同的數據類型,你必須使用所有值類似VARCHAR(n)的。你失去了類型安全和聲明約束。 (您不能檢查key3的值是否在1和15之間,而key7的值是在0和3之間。)


這可行嗎?

這種結構(稱爲「EAV」 - 谷歌的那種)是一種衆所周知的餐桌設計反模式。問題的一部分是你基本上將列存儲爲行。 (您在key_value_store.key_name中存儲了列名。)如果您有有史以來必須以正常表的格式寫出數據,您會發現三件事。

  1. 很難編寫查詢來輸出正確的格式。
  2. 需要永久運行。如果您必須編寫數百個列,它可能永遠不會完成。
  3. 你會希望你有更快的硬件。很多,很多更快的硬件。

我尋找什麼

  • 機遇組鍵進入邏輯表。這與第一個設計有關,它可能不適用於你。這聽起來就像你的應用程序基本上存儲了一個日誌文件,並且你不知道每次運行哪些鍵會有值。
  • 減少行數的機會。我會問,「我們可以少寫一遍嗎?」所以我會考慮每5秒或6秒寫入數據庫,而不是每3秒寫一次,假設這意味着我正在寫更少的行。 (真正的目標是更少的行數,而不是更少的寫入數量。)
  • 合適的平臺。 PostgreSQL 9.2可能是更好的選擇。版本9.2具有僅索引掃描,並且它具有實現鍵值存儲的hstore模塊。

測試你決定

如果我是你的話,我會在這兩個MySQL和PostgreSQL構建這個表之前。我會加載大約一百萬行隨機數據。然後,我會嘗試一些查詢和每個報告。 (報告很重要。)衡量績效。將負載增加到1000萬行,重新調整服務器和dbms,然後再次運行相同的查詢和報告。再次測量。

重複1億行。當你有信心時退出。預計這一切需要幾天。

+0

優秀的分數,Catcall。 – n8wrl

+0

@YannicDoNotText:2.5GB。我打開了兩個電子表格,並將其選中到錯誤的中間。計算爲每分鐘20次寫入;每寫入20 * 100(2000)行;每天2,880,000行;每月8640萬行;每行28個字節;每月2419,200,000字節。這是很多行。 –

+0

是的。我知道。但我必須這樣做。這是一個有3個月曆史數據的監測項目......你認爲這有可能嗎?有了建議的ERM?第一行和第100列的建議是錯誤的,不是嗎? –

1

我不會太在意數據庫的大小。你更大的問題是維護和靈活性。

這是我會做的。首先,定義並填寫此表,可能的密鑰的設備可以這樣寫:

tblDataKey 
(
    ID int primary key (auto-increment - not sure how mysql does this) 
    Name varchar(32) 
) 

下一個定義「數據事件」表:

tblEvent 
(
    ID int primary key (auto-inc) 
    TimeStamp 
    ...anything else you need - device ID's? ... 
) 

然後配合按鍵事件和它們的值:

tblEventData 
{ 
    EventID INT FK-to-tblEvent 
    KeyID INT FK-to-tblDataKey 
    DataValue varchar(???) 
) 

現在需要每然而,許多秒的數據來自於您創建tblEvent與鍵值單個條目多個條目tblEventData。並非每個事件都需要每個密鑰,並且您可以在未來擴展密鑰。

這真正的亮點在空間不浪費,你可以很容易地與特定的數據鍵和值evnets做查詢。在這種結構下降的情況下,當你需要製作「交叉表」式的事件和數據項目表時。你必須決定是否有問題。

+0

嗨n8wrl,謝謝你的回答。 我試過了,就像你描述的那樣。你可以來看看嗎? http://ondras.zarovi.cz/sql/demo/?keyword=tempidi2 –