38

我們的數據庫是基於EAV(Entity-Attribute-Value)模型設計的。那些與EAV模型合作過的人都知道爲了靈活性所帶來的所有弊端。實體屬性值(EAV)的替代方法?

我問我的客戶有關使用EAV模型(靈活性)的原因,他們的回答是:他們的實體隨時間變化。所以,今天他們可能有一個有幾個屬性的表,但在一個月的時間裏,可能會添加一些新的屬性,或者現有的屬性可能會被重命名。他們需要生成報告以及時回到任何階段,並根據該階段的實體形狀查詢數據。

我明白這對傳統的關係模型是不可行的,但我個人認爲EAV是反模式。是否有其他可供選擇的模型使我們能夠捕捉實體和實例更改中的時間維度?

乾杯, MOSH

+2

與其取代你所擁有的東西,因爲它確實滿足特定的需求,你應該考慮用隨時間存儲變化的東西來擴充你的基本EAV模型。 – RibaldEddie 2010-10-29 05:24:29

+0

我同意RibaldEddie,它不會很簡單,但爲您的Attribute定義添加日期/版本可能會比完全重構構建在當前架構上的所有代碼更容易。 – JeremyWeir 2010-10-29 05:47:03

+4

有沒有可能關閉這個?無論是評論和進展,還是投票和選擇答案。謝謝。 – PerformanceDBA 2011-01-25 12:32:33

回答

-1

爲每個實體描述版本 和一個附加表,告訴你哪個表是哪個版本的新表的說明。 查詢系統也應該更新。

我認爲創建一個腳本生成,表和查詢是你最好的選擇。

8

無論您使用哪種關係模型,跟蹤字段名稱更改都需要大量的元數據,您必須在事務日誌或審計表中跟蹤這些元數據。不幸的是,在某個特定日期查詢這些狀態是非常複雜的。如果您的客戶端僅在特定時間日期需要狀態,則意味着整個狀態,而不僅僅是名稱更改,您可以複製數據庫並將事務日誌回滾到所需的特定時間,並對新實例運行查詢。如果在指定日期之後添加的實體需要使用舊字段名稱顯示在查詢中,那麼在您面前有一個非常大的工程問題。在這種情況下,根據您在問題中提供的信息,我會建議與客戶協商替代方案,或者獲取有關使用報告的更多信息以尋找替代解決方案。

您可以移動到基於文檔的數據存儲,但仍不能解決第二種情況中的問題。很抱歉,這不是一個真正的答案,但是在類似的情況下,客戶可能需要一個更現實的報告解決方案或其他一些願意爲工程提供資金的投資者。

當我們遇到這個問題時,我們保持數據庫模式不變,並實現基於時間戳的實體映射工廠。最後,客戶不斷地改變需求(每週到每月),計算總計字段的方式,並且從未完全滿意。

+1

優秀的迴應。我會補充說一些客戶將會完全不滿意,因爲他們不接受數據模型的最終靈活性和長期一致性之間的權衡。你只需要學習如何管理這些客戶,並防止他們破壞你的生活或你的聲譽。 – 2010-10-29 15:19:42

46

EAV完全忠誠或嚴重不同; 5NF由技術熟練的人員或無知者完成。

第六範式是不可簡化的範式(不需要進一步的標準化)。它消除了很多常見的問題,如The Null Problem,並提供了識別缺失值的最終方法。這是在學術和技術上強大的NF。沒有產品可以支持它,它不常用。要正確和一致地實施,它需要一個元數據的目錄來實施。當然,導航它所需的SQL變得更加繁瑣(SQL重新連接繁瑣),但是通過從元數據中自動生成SQL可以輕鬆解決這個問題。

EAV是6NF的部分集合或子集。問題在於,通常是爲了某種目的(允許添加列而無需進行DDL更改)以及不知道6NF的人以及不實現元數據的人員完成的。重點是,6NF和EAV作爲原則和概念提供了實質性的好處,並且性能提高;但通常它沒有得到正確執行,而且沒有實現好處。不少EAV的實施都是災難性的,不是因爲EAV不好,而是因爲實施效果差。

例如,有些人認爲從6NF/EAV數據庫構建3NF行所需的SQL很複雜:不,這很麻煩但不復雜。更重要的是,可以提供普通的SQL VIEW,這樣所有的用戶和報表工具都只能看到直接的3NF VIEW,而6NF/EAV問題對他們來說是透明的。最後,所需的SQL可以自動化,因此很多人忍受的人工成本是不必要的。

所以答案的確是,第六範式,是EAV的父親,是一個更純粹的形式,是它的替代品。注意事項是,確保它正確完成。我有一個大的6NF數據庫,它沒有任何人員發佈的問題,它執行得很漂亮,客戶很高興(沒有進一步的工作是完全功能滿意的標誌)。

我已經發布了一個非常詳細的回答另一個問題,它適用於你的問題還有,你可能會感興趣。

Other EAV Question

0

爲了增加從@NickLarsen和@PerformanceDBA答案

如果您需要跟蹤字段名稱等歷史更改,您可能需要查看諸如Slowly Changing Dimensions之類的內容。在我看來,您似乎正在使用EAV來建模動態維度模型(可能是查找列表)。

實現此目的最簡單(也可能是效率最低)的方法是在EAV表中包含一個「至」日期字段,並且每當發生更改時,都會插入一條新記錄(而不是更新現有記錄)當前日期。這意味着您需要更改查詢以始終包含或查找「截至」日期,或者如果沒有提供,可以將其刪除爲「now」。然後,加入EAV對象的基礎實體必須從EAV表中查詢「top 1」,其中「asof」日期小於或等於該行的「最後更新」日期,按照「asof」降。最糟糕的情況是,如果您需要跟蹤給定行的最近更改,其中名稱(存儲在'屬性'表中)和值已更改,則可以使用'上次修改'將此邏輯鏈接到值表找到該特定日期的適當值。

如果有很多變化,這顯然有可能產生大量的數據。這就是爲什麼這種方法被稱爲「緩慢」變化的原因。它適用於可能會更改的尺寸值,但不是很常見。爲了幫助提高查詢性能,「as of」和「last modified」字段上的索引應該有所幫助。