我在大學時上數據庫的課程,學的三個范式中有個第三范式就是專指的外鍵約束。可是出來工作以后第一次做數據庫表設計的時候,組長大佬卻讓我在數據庫中不要使用外鍵,改在代碼中做相應處理。說得專業點,就是不要在數據庫中使用物理外鍵,改為使用邏輯外鍵,即在代碼中寫相關的邏輯代替外鍵所起的作用。我從此便懂得了,解決實際的問題要從實際出發,不能照本宣科。
外鍵的作用
1.外鍵能保證數據的完整性。在沒有外鍵的情況下,數據庫就不能強制進行引用完整性檢查,如果在高一層沒有進行正確的處理,則可能會導致數據出現不一致的情況。
2.外鍵能使表之間的關系變得清晰。如果數據庫中缺少外鍵,不了解表之間關系的人很難找到正確的關聯表,這樣可能會導致嚴重的數據庫查詢問題(關聯錯表、查錯表)。
為什么數據庫可以沒有外鍵
既然外鍵有那么多好處,為什么這里說設計數據庫的時候可以不要外鍵呢,想作死嘛?但是世事無絕對的,這個世界也不是非黑即白的,很多時候人生只能隨波逐流,跟着環境改變。意思就是說,數據庫設計還是要根據實際情況,其實有7個理由可以說明為什么數據庫可以沒有外鍵。
1.提高性能
在表上擁有活動的外鍵可以提高數據的質量,但是會影響插入、更新和刪除操作的性能。因為在這些操作任務之前,數據庫需要檢查它是否違反數據完整性。這就是為什么一些架構師和DBA完全放棄外鍵的原因。數據倉庫和分析數據庫尤其如此,這些數據倉庫和分析數據庫不以業務方法(一次一行)處理數據,而是批量處理數據。性能是數據倉庫和商業智能的一切。
2.方便舊數據的導入
許多數據庫在設計的時候需要考慮導入來自舊數據庫的數據的因素。這些數據可能對數據的質量和完整性沒有那么嚴格,為了能夠容納舊的臟數據,架構師有兩個選擇,一是清理和轉換舊的歷史遺留數據(昂貴代價,需要人工去編制數據);二是放棄在數據庫級別上強制執行參照完整性。哪個方法更好更節約成本更高效,我相信已經不言而喻了。
3.方便全表的重新加載
一些數據庫,如數據倉庫,分段或接口數據庫,需要經常從外部重新加載數據。就像你本地的測試數據庫需要從生產環境的正式數據庫重新加載數據一樣。這可能會導致重新加載數據時數據不一致(在父表為空的情況下,子表可能已經裝滿)。雖然可以通過在重新加載數據的時候禁用外鍵來繞過這個問題,然而這卻引入了額外的邏輯和復雜性,以及另一個失敗點,對性能有負面影響。
4.將外鍵起的作用交給更高層次的框架完成
一些應用程序使用編程框架,在物理數據庫之上創建另一個邏輯層,開發人員不需要編寫插入或更新語句來修改數據,而是調用提供的API在后台執行所有操作。ORM(對象關系映射)框架比如Hibernate就是這種情況,這些框架負責維護參照完整性,並與RDBMS一起創建更高級別的數據庫引擎。
5.方便跨數據庫
在一些大型系統,可能會有很多個數據庫。比如說A表在A數據庫,B表在B數據庫,你想在A表和B表之間創建外鍵是不可能的。當然你可能會說A表和B表要創建外鍵就把A表和B表放在一個數據庫里面啊,但是我偏不,嘿嘿。
6.節約一些工作成本(偷懶/提高效率)
在創建數據庫的時候,如果要存儲數據,最低限度是要創建一些表和一些字段。但是創建一些保證數據一致性的結構卻不是必須的工作,比如外鍵等約束。這些工作需要人力和時間成本,但是卻沒有帶來直接的好處。因此很多架構師和DBA都選擇忽略掉這一部分。
7.讓你在團隊里變得不可替代
在現實的社會中,很多人都希望被需要和不可被替代。如果數據庫表的設計者是你且只有你,那么表之間的關系就只有你知道,別人要知道表之間的關系就只能通過你,你就變成了不可替代的那個人了。當然在現實中是不可能的,數據庫設計都是要留存的,比如說PDM;你也不可能成為不被替代的那個人。沒有錯,現實就是那么殘酷。
"世界上沒有誰是不可替代的,一個人離開了,馬上就會有另外一個人取代他的位置。"