2012-09-30 45 views
0

這種情況:何時沒有規範化的數據庫?

比方說,我有一個狗模型和一個疫苗接種模型(所以,一張表存儲行的狗和一張表存儲給狗的疫苗行)。

所以,一隻狗has_many接種疫苗和疫苗belongs_to一隻狗。

我想快速回答這個問題:「狗A最後一次接種疫苗的時間是?有兩種方法來存儲此數據:

1)規範化的數據庫方式:讓Vaccine表存儲所有內容。要回答這個問題,請在數據庫中搜索給狗A的所有接種疫苗,然後返回最近的疫苗。

2)不規範化數據庫的方式:有一個名爲「last_vaccination」在狗場,而每一個疫苗是給犬A.時間

#1的優點是保持這一領域的:你得到數據庫規範化並且不必擔心維護準確的數據。

#2的優點是:性能 - 您無需每次都搜索疫苗數據庫。

什麼是正確的做法?

+0

這顯然是一個非常簡單的例子,規範化的原因是每個表中的主鍵具有特定的數據。我會說你想盡可能規範化你的表格,否則你最終會得到一張存儲所有數據的表格。 –

回答

4

我是一個大風扇的一種說法,幾年前,我從一個軟件研討會一個DB傢伙聽到:

「正常化直到它傷害,直到它正常工作。」

很多事實。

FWIW,我認爲在上面的佈局中有一個漏洞 - 一個「疫苗接種」表需要在那裏,實際上,狗與疫苗聯繫在一起。疫苗!=疫苗。這是規範化版本的更準確表示。 IMO。

+0

同意。接種疫苗是一種與狗和疫苗具有多對多關係的表。它至少有4列:id(PK),dog_id(FK),vaccine_id(FK),vaccination_date。 –

+0

@DavidW讓我們假設只有一種疫苗接種。我更新了這個問題以反映這一點。 – Tim

0

個人,那我來在這樣的情況下實現的事情之一是:

如果你發現需要不斷的聚合存儲或「最新的記錄」在另一個表信息(和打破正常化) ,主要用於性能目的,那麼你真正需要的是一個緩存,而不是的一列/表。

選擇你的毒藥:簡單的內存中緩存,分佈式緩存或NoSQL補充到您的RDBMS。

在您的特定情況下,最簡單的事情能夠工作可能會去是這樣的:

Rails.cache.fetch("dogs/#{@dog.id}/last_vaccination") do 
    @dog.vaccinations.last 
end 
+0

所以你說的是,我仍然需要實現業務邏輯來更新緩存,每次添加新記錄時,對吧? – Tim

+1

您可以使用'@ dog.cache_key'而不是'@ dog.id'。它包含updated_at時間戳,可確保緩存始終保持新鮮。每次添加新疫苗時,請確保時間戳已更新:'Vaccination.belongs_to:dog,touch:true' –