2010-12-19 160 views
15

我們必須重新設計一個傳統的POI數據庫,從MySQL到PostgreSQL。目前,所有實體都具有代表各個屬性的80-120 +個屬性。是EAV - Hybrid是一個糟糕的數據庫設計選擇

我們被要求考慮新的數據庫的靈活性和良好的設計方法。但是新的設計應該允許:

  • ň沒有。任何實體的屬性/屬性,即任何實體的屬性都不固定,並且可能會定期更改。

  • 允許內容管理員通過管理界面使用動態爲現有實體添加新屬性,而不是始終對數據庫模式進行更改。

大約有EAV的性能問題,相當多的討論,但如果我們不以混合EAV去我們結束了:

  • 有很多空列(我們還是去即使99%的數據沒有這些屬性,也要添加新的列)
  • 花費更多時間維護數據庫。當屬性不斷變化時。
  • 沒有允許內容管理員,以新的屬性添加到現有的實體

反正這裏的路是我們正在考慮的新的設計內容(包括基本ERD):

  • 對每個單獨的表包含一些基本信息的實體,例如編號,名稱,地址,聯繫人,創建等等

  • 有2個表屬性類型和屬性來存儲屬性信息。

  • 使用多對多關係將每個實體鏈接到一個屬性。

  • 將地址存儲在不同的表中並鏈接到使用外鍵的實體。

alt text

我們認爲,這將允許我們添加,刪除或更新的屬性時更加靈活。

然而,這種設計會在獲取數據時增加連接數量,例如顯示給定體育場的所有「屬性」,我們可能會用20多個連接查詢來獲取單行中的所有相關屬性。

你對這個設計有什麼想法,你有什麼建議來改進它。

謝謝您的閱讀。

+0

看看是否使用NOSQL數據庫將有所幫助? http://nosql-database.org/ – 2010-12-19 05:53:41

+0

您不需要NoSQL以JSON或XML格式將數據存儲在數據庫表的字段中,並且使用PostgreSQL可以在特定字段上創建功能索引 – MkV 2010-12-19 07:20:59

+2

生產數據庫中的字段shouldn '不會被'添加',應該有一些改變控制來防止數據混亂。通過做一些前期設計避免這種情況。根據需要添加表格,或者在字段爲1-1的情況下將字段添加到現有表格,並且不會更改表格。 – MkV 2010-12-19 08:39:25

回答

1

基本上EAV試圖在數據庫中實現一個數據庫,並導致瘋狂。拉取數據的查詢變得過於複雜,並且您的數據沒有穩定的特定模型來保持它的某種順序。

我已經爲有限的應用程序編寫了EAV系統,但作爲一個通用的解決方案,它通常是一個壞主意。

+0

好的一點。你在處理數十個是/否屬性不斷變化的建議時有什麼建議? – nka 2010-12-19 15:20:49

+0

序列化數據並在應用程序中處理它 – 2010-12-19 16:19:54

+5

但是,如果您將「屬性」字段中的所有屬性存儲爲blob,如何使用屬性過濾查詢?這必須在應用程序中完成,如果我們談論許多結果,這可能導致高(不必要的)內存消耗。 – acme 2011-01-26 11:30:04

6

EAV可用於某些場景。但它有點像「黑暗的一面」。強大,靈活,非常誘惑它。但這是一個簡單的方法。一個簡單的方法來做適當的分析和設計。

我認爲「實體」有點過於頂級過於籠統。您似乎對連接到該實體的內容有一些瞭解,例如地址和聯繫方式。如果您決定在模型中使用「書籍」,該怎麼辦?他們是否也有地址和聯繫人?我認爲你應該嘗試找到正確的概括,並將模型的EAV部分保持在最低限度。每當你發現自己想要顯示屬性的某個子集,或者測試該值的存在,或者根據該值確定行爲時,你應該將它建模爲列。

你不會得到比現在更好的設計這個系統的機會。自從以前的版本以來,這些要求是已知的,並且還有哪些是有效的,哪些沒有。 (只是不要成爲Second System Effect的犧牲品)

+1

感謝您的答案。那麼有什麼更好的方法呢。比方說,如果我們有100 +是/否標誌附加到每個實體,你會打破它們並將它們分組後通過categeory(通過很多這些標誌被許多表共享)單獨存儲。這些標誌集可以使用外鍵鏈接到不同的實體? – nka 2010-12-19 15:15:14

+0

現在隨着你最後的評論,我看到你正在嘗試做什麼。對於「有廁所」,「出售糖果」等一系列是/否的標誌,我想我也會使用屬性/價值模型。您基本上爲您的興趣點做了一個奇特的標記系統,並增加了一些元數據。我被名稱「實體」誤導了。 – Ronnis 2010-12-19 17:48:14

27

我正在維護一個擁有10M +實體,50​​0M +值和數百個屬性的中央EAV模型的10年曆史的系統。根據我的經驗設計一些注意事項:

如果您有適用於特定屬性的任何業務邏輯,則值得將該屬性作爲顯式列。 EAV屬性實際上應該是通用的東西,應用程序不應該區分屬性A和屬性B.如果在代碼中找到對EAV屬性的文字引用,則可能性是它應該是明確的列。

有大量的空列是不是一個大的技術問題。它需要良好的編碼和文件的做法來劃分,在一個表中結束了不同的擔憂:

  • 有約定,並且讓你知道哪些應用程序的一部分讀取和修改數據的哪一部分的規則。
  • 使用視圖來減輕使用調試工具在數據庫中的影響。
  • 創建並維護測試數據生成器,以便您可以輕鬆地爲您目前不感興趣的模型部分創建符合架構的虛擬數據。
  • 使用嚴格的數據庫版本控制。進行模式更改的唯一方法應該是通過一種跟蹤和應用更改腳本的工具。 Postgresql具有事務性DDL,這是用於自動化模式更改的一個殺手級功能。

Postgresql並不真的喜歡瘦的表。除了遍歷所有行以將數據拉到一起的額外工作外,每個屬性值還會導致32字節的數據存儲開銷。如果您主要讀取和寫入屬性作爲批處理,請考慮以某種方式將數據序列化到行中。 attr_ids int[], attr_values text[]是一個選項,hstore是另一個選項,或者是客戶端,如json或protobuf,如果您不需要觸摸數據庫端特定的任何東西。

不要爲了將所有東西放在一個單獨的實體表中而想盡辦法。如果他們沒有以合理的方式共享任何屬性,請使用您使用的特定EAV模式的多個瞬間。但是,儘量使用相同的模式並在不同的instatiations之間共享任何訪問者代碼。您始終可以參數化實體名稱上的代碼。

請務必記住,代碼是數據,數據是代碼。您需要找到將決策推入元模型並將其作爲代碼表達的正確平衡點。如果你使元模型做得太多,修改它就需要相同的能力來理解系統,版本管理工具,QA過程,作爲你的代碼登臺,但它沒有任何工具。實質上,你將會用非常尷尬的非標準語言進行編程。另一方面,如果你在代碼中留下太多內容,每一個微小的變化都需要一個新版本的軟件。人們傾向於使元模型過於複雜。爲元模型構建開發人員工具是困難且乏味的工作,並且效益有限。另一方面,通過自動執行從提交到部署所發生的所有事情,使發佈過程更便宜有很多好處。

+0

感謝您的回覆,我們試圖使用混合eav模型,其中每個實體都有自己的表和屬性,但只有常用屬性保存在「屬性」表中,您可以將其視爲標籤,以便我們能夠創建或附加任何數量的標籤給任何給定的實體。 – nka 2010-12-25 01:43:18

+0

而不是爲某些邏輯使用列,如何創建兩種屬性,簡單和困難的屬性。硬屬性可以在代碼中擁有業務邏輯嗎? – djmj 2013-01-06 00:39:40

3

EAV的一個很好的實現可以在magento中找到,它是電子商務的一個cms。那些日子裏有很多關於EAV的壞話,但我挑戰任何人提出另一個解決方案,而不是EAV來處理無限的產品屬性。

當然,您可以列舉世界上每種產品所需的所有列,但這會花費您很多時間,並且您將不可避免地忘記產品屬性。

因此,底線是:使用EAV作爲無限的東西,但不要依賴EAV來處理所有數據庫的表格。因此,如果做得對,混合EAV和關係數據庫是一個功能強大的工具,只能使用固定列才能實現。

+0

postgresql中的JSON是另一種選擇。 – 2015-09-29 14:48:24

相關問題