SQL反模式學習筆記6 支持可變屬性【實體-屬性-值】

  • 2019 年 10 月 4 日
  • 筆記

目標:支持可變屬性

反模式:使用泛型屬性表。這種設計成為實體-屬性-值(EAV),也可叫做開放架構、名-值對。

優點:通過增加一張額外的表,可以有以下好處

(1)表中的列很少;

(2)新增屬性時,不需要新增列。不會影響現有表的結構;

(3)存儲的字段內容不會為空值。

缺點:(1)查詢語句變得更加複雜;

(2)使用EAV設計後,需要放棄傳統的數據庫設計所帶來的方便之處,比如:無法保障數據完整性;

(3)無法使用SQL的數據類型,比如對日期、金錢等格式內容都只能保持為字符串類型;

(4)無法確保引用完整性;

(5)無法配置屬性名。比如,有可能表中存在兩條記錄,

一條的attr_name是sex,一條attr_name是gender,都是表示性別;

(6)查詢結果中有多個屬性時,查詢非常困難,且查詢性能無法控制。

如何識別反模式:當出現以下情況時,可能是反模式

  (1)數據庫不需要修改元數據庫(表中的列屬性)就可以擴展。還可以在運行時定義新的屬性。

  (2)查詢是連接數量非常多,且連接的數量可能會達到數據庫的限制時,你的數據庫的設計可能是有問題的。

  (3)普通的報表查詢變的及其複雜甚至不且實際。

合理使用反模式:

  (1)關係數據庫中使用EAV,就意味着放棄許多關係數據庫範式的優點。

但是這不影響在某些程序中合理地使用這種設計來支持動態屬性。

  (2)如果有非關係數據管理的需求,那最好的方法就是使用nosql數據庫。

在傳統數據庫中使用EAV設計的缺點也體現在這些非關係數據庫上。當元數據不具有固定格式時,

再簡單的查詢都會變得非常困難。上層應用就需要花費更多的時間、精力來組織數據結構。

解決方案:模型化子類型

  1、單表繼承:所有屬性都在一個單表上保存,增加屬性時就擴充這個表。

當數據的子類型很少,以及子類型特殊屬性很少,就可以使用單表繼承。

缺點:(1)當程序需要加入新對象時,必須修改數據庫來適應這些新對象。又由於這些新對象具有一些和老對象不用的屬性,

因而必須在原有表裡增加新的屬性列,可能會遇到一個實際的問題,就是每張表的列的數量是有限制的。

(2)沒有任何的元信息來記錄哪個屬性屬於哪個子類型。

  2、實體表繼承:為每個子類型創建一張獨立的表,每個表包含哪些屬於基類的共有屬性,同時也包含了子類型特殊化的屬性。

優點:(1)實體繼承類設計相比於但表繼承設計的優勢在於提供了一種方法,

讓你能組織在一行內存儲一些和當前子類型無關的屬性。

如果你引用一個並不存在於這張表中的屬性列,數據庫會自動提示你錯誤。

(2)不用像在單表繼承設計里那樣使用額外的屬性來標記子類型。

缺點:很難將通用屬性和子類特有屬性區分開來。因此,如果將一個新的屬性增加到通用屬性中,

必須為每個子類表都添加一遍。

當你很少需要一次性查詢多有子類型時,實體繼承表設計是最好的選擇。

  3、類表繼承:把表當成面向對象里的類。

創建一張基類表,包含所有子類型的公共屬性。對於每個子類型,創建一個獨立的表,通過外鍵和基類表相連。

  4、半結構化數據模型:如果有很多子類型或者必須經常增加新的屬性支持,那麼可以用一個BLOB列來存儲數據,

用XML或者JSON格式——同事包含了屬性的名字和值。這叫做序列化大對象塊。

   這個設計的優勢是擴展性,缺點是,這樣的結構中sql無法獲取某個指定的屬性。你必須或者整個blob字段並通過程序去解釋這些屬性。

    當你需要絕對的靈活性時,可以使用這個方案。

如果使用了EAV,那麼可以先將全部屬性取出,然後再做其他處理。