我們在我們的應用程序中需要存儲引用以供以後訪問。數據庫歷史化
示例:用戶可以一次提交發票,並且該發票包含的所有參考(客戶地址,計算的金額,產品描述)和計算應該隨時間存儲。
我們需要以某種方式保存參考文獻,但如果例如產品名稱更改?所以我們需要複製一切,以便以後記錄下來,而不會受到未來變化的影響。即使產品被刪除,他們也需要在發票存儲後再進行審覈。
這裏關於數據庫設計的最佳實踐是什麼?即使最靈活的方法是什麼當用戶想要稍後編輯他的發票並從數據庫恢復它?
謝謝!
我們在我們的應用程序中需要存儲引用以供以後訪問。數據庫歷史化
示例:用戶可以一次提交發票,並且該發票包含的所有參考(客戶地址,計算的金額,產品描述)和計算應該隨時間存儲。
我們需要以某種方式保存參考文獻,但如果例如產品名稱更改?所以我們需要複製一切,以便以後記錄下來,而不會受到未來變化的影響。即使產品被刪除,他們也需要在發票存儲後再進行審覈。
這裏關於數據庫設計的最佳實踐是什麼?即使最靈活的方法是什麼當用戶想要稍後編輯他的發票並從數據庫恢復它?
謝謝!
下面是做到這一點的一種方法:
本質上說,我們從來沒有修改或刪除現有的數據。我們通過創建新版本來「修改」它。我們通過設置DELETED標誌來「刪除」它。
例如:
注意事項:
該模型使用了很多識別關係。這導致了「胖」的外鍵,並且可能存在一些存儲問題,因爲MySQL不支持前沿索引壓縮(不像Oracle),但另一方面,PK上的這種集羣可能是有益的表現。另外,JOIN不需要。
與非識別,關係和代理鍵等效模型是這樣的:
您可以在產品表中添加一列,指示是否正在銷售。然後,當產品被「刪除」時,您只需設置標誌,使其不再作爲新產品提供,但您保留數據以備將來查找。
要處理名稱更改,您應該使用ID來引用產品,而不是直接使用名稱。
您正面臨的問題是,我相信您知道,數據庫規範化的結果。解決此問題的方法之一可以從商業智能技術中獲取 - 將數據歸檔爲Data Warehouse中的非歸一化狀態。
標準化數據:
當查詢和存儲反規範化,數據倉庫表看起來像
通常,要麼是某種按計劃將數據從規範化數據提取到數據倉庫的預定作業,或者如果您的計劃作業符號允許,可以在訂單達到某個狀態時完成。 (如發貨)可能是記錄在每次狀態更改時都會存儲(有一個名爲OrderStatus的字段會增加當前狀態),因此完全取消規範化的數據適用於oprder /履行過程的每個步驟。何時以及如何將數據歸檔到倉庫中會根據您的需求而有所不同。
上面涉及很多開銷,但我知道的另一種常見方法會帶來更多開銷。
另一種方法是將表格設置爲只讀。如果客戶想要更改他們的地址,則不需要編輯他們現有的地址,而是插入新的記錄。
因此,如果我的地址是AddressId 12,當我在Jamnuary的網站上進行第一次訂購時,那麼我將在7月4日移動,我會得到一個與我的帳戶綁定的新AddressId。 (說AddressId 123123因爲你的網站是非常成功的,並已吸引了一噸的客戶)。
令我7月4日之前將地點理想有AddressId與它們相關的12,並放置7月4日或之後的訂單已經AddressId 123123.
對每個需要保留歷史數據的表格重複該模式。
我確實有第三種方法,但搜索它很困難。我只在一個應用程序中使用它,並且在單個實例中實際運行得非常好,它具有與特定時間點完全相同的重構數據的特定業務需求。除非我有類似的業務需求,否則我不會使用它。
在特定狀態下,將數據序列化爲Xml文檔或其他可用於重建數據的文檔。這使您可以保存數據,因爲它在序列化時保留原始表結構和關係。
你在純粹主義和實用主義之間展開了一場永恆的辯論。
從數據庫的規範化角度來看,您應該「保留」所有相關數據。換句話說,如果產品名稱發生變化,請保存更改的日期,以便您能夠及時回溯並使用該產品名稱以及當天存在的所有其他數據重建發票。
「de」標準化方法是將該發票視爲「時刻」,並在相關表格中記錄當天的實際數據。這種方法可以讓您在沒有任何依賴關係的情況下提取發票,但是您無法從頭開始重新創建發票。
當您有時間敏感數據時,您可以使用產品和客戶表等信息作爲查找表,並將信息直接存儲在您的訂單/訂單細節表中。
因此,訂單表可能包含客戶名稱和地址,詳細信息將包含有關產品的所有相關信息,包括特別是價格(除了初始查找時,您絕對不希望依賴產品表獲取價格信息命令)。
這不是反規範化,數據隨時間變化,但您需要歷史數據,因此您必須在創建記錄時存儲數據,否則將失去數據完整性。你不希望你的財務報告突然顯示你去年賣出了30%,因爲你有價格更新。這不是你賣的東西。
「這不正常化......」是的。在關係系統中,重複數據意味着「具有相同含義的相同值」。這裏的值可能是相同的,但含義不同。 (當前價格,例如,與訂單時的價格相比。) –
要擁有唯一的產品名稱,您可以添加一個僅包含產品名稱的表格,其中名稱是pk,並鏈接到PRODUCT_VERSION的表格 –
@OweJessen當然,您可以使用唯一的NAME包含LATEST_PRODUCT_VERSION表,但不包含算作「聲明式」解決方案,因爲在創建新產品版本時,您需要手動插入和刪除該表中的行。除非您使用的DBMS既可以自動更新實例化視圖,也可以實現它們的唯一性(例如MS SQL Server的索引視圖),因此DBMS本身會爲您維護LATEST_PRODUCT_VERSION。 –