2014-01-31 53 views
1

我目前正試圖模擬系統的一個方面,從而存儲的組件可以更改狀態,例如OK,FAILED,REPAIRED等。在Web端我需要顯示當前狀態,還有以前(如果有的話)狀態的歷史。我在這兩種設計之間徘徊,任何人都可以在最好的方式(我更像是一個軟件開發人員而不是dba人員)上有任何改變。用於跟蹤狀態變化的最佳表格結構

選項之一:

其中每個時間的狀態變化跟蹤statehistory表中,最高序列號將是當前狀態:SQLFiddle example

方法二: 與上述類似,不同之處的當前狀態被存儲在組件表中,只有歷史狀態在歷史表中。當狀態改變時,當前狀態被插入爲歷史中最近的狀態,那麼電流被設置在組件表中:SQLFiddle example

另外,使用一個或兩個,但沒有狀態查找表,只需存儲狀態文本爲varchar(我的想法是這樣可以更容易地報告?):SQLFiddle example

謝謝。

編輯:

有幾種成分表,如果狀態歷史表中包含的數據,所有的人,或使每一個成分表statehistory?每個組件表都會有成千上萬的條目,這使得狀態歷史表非常大。

如: 表:component_a 表:component_b 等。 statehistory( component_a_id, component_b_id, STATE_ID, ... )

+0

個人而言,我會選擇http://sqlfiddle.com/#!6/f8555 - 但是,我會選擇一個'DATETIME'而不是一個整數'SEQUENCE' – MarkD

+0

任何特定原因的日期時間超過int序列? –

+1

'DATETIME'會提供比INT更多的信息。 'DATETIME'會用'MAX'表示最近的(與'INT'一樣),但它實際上會告訴你什麼時候。再次,我的意見。 – MarkD

回答

1

我傾向於做兩者之間的混合體。我始終將所有狀態更改(包括當前狀態)存儲在歷史記錄表中。這給你一個查詢它們的中心位置。你可以有一個專欄IsCurrent BIT NOT NULL讓你的生活變得更輕鬆。使用過濾器IsCurrent = 1創建過濾的唯一索引以強制執行基本的完整性規則。

我還將當前狀態存儲在主表中。可能不只是一個副本,而是作爲歷史表的外鍵。這使得查詢非常方便。查看當前狀態通常很有用。當然,對於索引原因,您也可以將值複製到主表中。系統複製越多,出錯率就越高。

如果您想要避免重複但仍索引當前狀態,您可以創建一個索引視圖來組合主表和歷史表。然後,您可以在兩個表的混合列上創建索引(例如,在(StatusHistoryItems.StatusComponents.Name))上支持查詢,以查詢具有特定狀態和特定名稱的客戶。此查詢將作爲視圖索引上的單個索引查找)。

你會創建這樣一個觀點:

SELECT * 
FROM Components c 
JOIN StatusHistoryItems shi on c.ID = shi.ComponentID 
    AND c.IsCurrent = 1 --this condition will join exactly one row 

並建立索引。現在,您可以將當前狀態與所有組件數據一起存儲在一個有效索引中。沒有重複,根本沒有反規範化。只要確保每個客戶至少有一個狀態行IsCurrent = 1

我建議每晚進行一次驗證作業,驗證數據一致性並提醒您有問題。由於各種原因,非規範化數據具有隨着時間推移而變壞的習慣。

+0

我喜歡將fk從當前組件存儲到歷史記錄表的想法 - 我沒有想到這一點,謝謝! –

+0

感謝這樣詳細的答案,我會用你的建議。我在原文中增加了一個額外的問題 - 你對此有何看法?謝謝。 –

+0

我寧願合併組件表,如果這在邏輯上合適的話。 「將有成千上萬的條目,使國家歷史表格非常大」不要陷入分裂表格的陷阱,希望更小的數據集更快。相反,應用適當的索引並且表的大小無關緊要。在性能的祭壇上犧牲數據模型的純度是非常罕見的。你很可能不是這種情況。 – usr