帶有 SQL 和實體框架的自引用表
我在數據庫中有很多表,這些表幾乎相同。目前對哪些對象引用其他對象存在限制。例如,我有公司、聯繫人和項目。聯繫人是公司的一個孩子,但與項目無關,儘管我們的一些使用者希望有。
由於這些表都是相似的,我想知道在每條記錄上創建一個具有類型屬性的自引用表是否是個好主意。表中的每條記錄都是特定類型,即公司、聯繫人等,並且有 X 個引用同一個表的外鍵欄位。
這使我們的使用者能夠創建自己的記錄類型並根據他們的選擇連結它們。
這會不會給我未來帶來任何我沒有想到的問題?我們的系統允許使用者在對像上創建自己的欄位,因此這看起來很完美。但他們也不能報告這些數據。性能方面我認為這應該沒問題,因為數據只會在 1 個表中。
關係建模從辨識“事物”的類別開始。對於這些,我們應用正規化來消除數據更新異常。結果以表格的形式實現,我們辨識的每個屬性都有一列。我們不是從一堆域開始,四處尋找具有相同域的“事物”,將它們硬塞到同一張表中並稱其為實體。這是一種反模式,通常稱為“一個真正的查找表”。實施它會影響可以定義哪些約束以及如何建立外鍵。表可能會因可 NULL 列而變得臃腫。這增加了完成查詢所需的 IO。索引深度增加,甚至會減慢關鍵查找。
現在,在每個項目的某個階段,標準化科學都會與模型設計藝術發生衝突。必須做出決定並接受妥協。在您的情況下,我可以看到出現的三種模型之一。
第一個是您目前擁有的規範化的。這就是 RDBMS 應該如何工作的。映射很明顯;查詢很快。但是,Exansion 需要更改架構,並且這些更改實施起來可能很慢,具體取決於您公司的能力。
第二種是超類型/子類型模型。您將 Company、Contact 等視為另一種類型的專業,例如 LegalPerson。這個超類型包含公共屬性。每個子類型都有特定的屬性。超類型和子類型之間存在一對一的關係,即給定的“事物”必須在超類型中有一行並且恰好有一個子類型。這在目前的 SQL 產品中可能難以實施。這允許辨識實體類型之間的公共列。類型之間的關係保存在特定的外鍵列或交集實體中。數據的插入和操作更加複雜。同樣,模式的擴展將需要開發工作。
最後是實體屬性值(EAV)模型。在這裡,您正在有效地建構數據庫中的數據庫。您建模的對像是“表”和“列”,而不是“客戶”和“公司”。因此,您的應用程序可以隨意修改邏輯模式。代價是應用程序的複雜性和執行時性能。
EAV 的名聲不好。有很多文章解釋了為什麼只要大聲說出這個名字就會毀滅你。其他人為這種做法辯護。我自己有一個持有 300M 值的 EAV 系統。它對我們很有效。但我是故意這樣做的,完全理解其中的含義,有一個 DBA 團隊支持我,以解決我們無法解決的特定問題。它沒有完成,因為有些桌子看起來有點像其他桌子。