2014-02-07 42 views

回答

6

大多數時候,堅持正常化。除此之外,保持數據庫相當規範化有助於鎖定粒度。例如,如果您有一個包含兩個數組的「父」對象,則無法同時添加/更新/修改數組成員的事務。如果他們是常規的邊桌,你可以。 (如果需要序列化的行爲,您仍然可以在更新子對象之前使用SELECT ... FOR UPDATE父行)。

更新一個數組以增加/替換/刪除一個值是很昂貴的,因爲PostgreSQL必須重寫整個元組作爲MVCC更新的。 (它有幾個TOAST可以幫助它,但不能噸)。嵌入在行中的同上複合類型。

充滿陣列和組合的寬大行意味着表掃描速度較慢,這意味着對常用值的較慢提取。

IIRC您無法將外鍵定義到組合類型的字段中,因此您會發現自己正在努力解決該問題,或者放棄參考完整性,因爲它應該是最好的。同上陣列(有was work to get foreign keys to arrays to work,但我認爲它從來沒有得到過)。

許多客戶端驅動程序(PgJDBC,psqlODBC,psycopg2等等)對數組和組合都有不完整或不存在的支持,所以您經常會將它們擴展爲用於客戶端驅動程序交互的元組。有些東西,比如複合類型的數組,真的很痛苦。

大多數ORMs,包括像Hibernate這樣的常見的ORM,完全習慣於使用超出最簡單的最低共同分母SQL特性之外的任何東西。遲早,有人會想要在你的數據模型中指出其中的一個,此時會出現許多哭泣和咬牙切齒的情況。 OTOH,不要容納垃圾ORM,避免使用會大大改善數據模型和解決真實世界問題的功能 - 例如,如果您可以選擇存儲本地hstore字段或使用EAV模式,考慮只使用jstore(或更好,在9.4中,具有hstore功能的json)。 (相反,這意味着擁有最多「面向對象」程序的人通常擁有最純粹的關係數據庫,因爲他們的工具很吸引人)。

類似報表生成工具的事情同樣會與組合和數組發生衝突,因此您經常會創建視圖來爲數據庫呈現規範化的外觀。然後ON INSERT OR UPDATE OR DELETE ... DO INSTEAD觸發視圖以啓用寫入。在哪一點它變得醜陋。

就我個人而言,我建議保留複合材料的時間是合理的,以便將某些東西建模爲「類型」。考慮一下,比方說,如果你的數據模型要求你跟蹤他們原來的時區的時間戳。這裏沒有內置類型(不,這不是什麼「帶時區的時間戳」,儘管名稱,謝謝SQL委員會),所以你可以創建一個複合類型,存儲(timestamp without time zone, tzname)並在數據模型中一致地使用它。

同樣,我傾向於在查詢中使用數組,而不是在數據模型中。當你想有意地將某些東西進行非規範化處理時,它們非常有用,但這通常是在物化視圖或類似視圖中完成的。即使這是對主數據模型的改變,也應該基於適當的性能評估來完成,而不僅僅是「優化」那些你不知道還是很慢的東西。

+0

謝謝,我注意到關於規範化的大多數故事從來沒有提到數組或複合材料,所以我想知道它們是否太新或是壞主意。但是如果你忘記ORM和不支持數組和組合的工具,將它用於任何複雜的東西仍然是一個糟糕的主意。 – rve

+0

感謝您寫這篇文章。真的幫助了我! –