mysql的資料庫設計到底該不該加約束,比如非空約束,外鍵約束等。因為我看到我們公司的DBA在設計資料庫結構的時候都是不加任何約束的,這樣對性能的提高有多大,會不會影響到數據的完整性。新手求大牛解答?
主鍵是默認唯一約束和非空約束的我知道,為了提高性能,其他所有的欄位都不應該加非空約束和唯一約束嗎?
學院派會告訴你在設計的時候把應該有的約束都加上
而實踐派得出的結論是主鍵一定加,非空約束盡量加,外鍵最好依賴於程序邏輯,而不是資料庫,從而更好的擁抱變化,快速響應,資料庫也會有相對較好的性能不知道你們是什麼公司,不過如果是互聯網公司,等到分庫分表的那一天你會想要把當年那個在資料庫上加了一堆約束的DBA拖出去TJJTDS……
主鍵約束一般必須。外鍵約束一般不加,參考完整性通過代碼保證,不能說由於代碼不健壯原因而加外鍵約束。同時增加外鍵約束會對邏輯實現過程中增加很多約束。非空約束也不要加,如果有明確的唯一性要求,可以加唯一性索引,唯一性索引自然會帶上非空約束。
對於日誌表,歸檔表,由於一般只做查詢,一般什麼約束都不加,減少數據插入或歸檔時候導致的索引開銷。
看業務對數據一致性的要求
1-約束盡量不加,能夠代碼邏輯內搞定的事情,就盡量不要麻煩資料庫。2-根據實際的查詢特性來設計索引。3-如果需要多個欄位來唯一標識,或者是 該欄位不具備遞增的特點,那就用自增主鍵,然後把欄位設定為UNIQUE KEY。
不設約束在極端情況下會影響數據的完整性和正確性,
設約束可能會對數據卸載轉移造成不便,會對寫入操作產生性能影響。資料庫本身橫向擴展性較差,容易發生硬體資源緊張,大多數系統設計中資料庫主要角色都是持久層,所以盡量轉移業務層邏輯到應用層比較好。具體情況具體分析啊
非空是建議加在有臟數據隱患,而且一旦有臟資料庫麻煩就很大的地方。
比如有個表裡面有wifi 和husband,然後你程序的邏輯是以這表只存已婚的夫婦為前提,那你一個空了就不好了,特別是設計了唯一鍵的你又不允許人家insert了,那你程序就要考慮insert_or_update的方式,又違背了初衷。
至於外鍵,我這裡答了個:
為什麼很多mysql課程不推薦用物理外鍵? - 知乎
用著用著就nosql了
性能提高:
我們試過,網上也有人測過,三四倍起碼。數據完整性:如果你沒有業務約束,那麼參照完整性和自定義完整性是極易被破壞的。
原理就不講了。除此之外,還包括各種範式什麼的,學會之後再忘掉就好了。
1 資料庫盡量作為數據的存儲 而非 業務邏輯的存儲,保留基本的主鍵約束,或者唯一約束足以。個人不推薦使用外鍵 trigger 存儲過程 ,分區表等2 思考業務量大的時候 ,如何快速拓展?
在測試時加外鍵,在正式產品中可取消外鍵
設計背景:
1、10年的系統,多是內部管理系統,數據量不會太大,所以學院派居多,只要有外鍵關係的,都設計了外鍵約束,看上去規範,但是實際編程起來並不理想。2、現在的系統,無論互聯網還是內部的,數據量都越來越大。所以外鍵的設計要審慎。外鍵的作用:
1、數據完整性約束2、外鍵索引,提高主從查詢的速度。外鍵的弊端:
1、分表、數據遷移難度大2、數據插入先後順序、非同步處理需要考慮周全。我的建議:1、外鍵有其必要,所以全庫都不用外鍵是不可取的。而且這樣如果主從表查詢,你還是一樣得增加額外索引,否則查詢速度會很慢。2、採用DDD領域驅動設計的邊界概念,領域模型內的子表,一般添加外鍵,對於跨領域模型的,不設計外鍵。
比如訂單子項表和商品表,購物子項表和商品表就不必設計外鍵。但是訂單主表和訂單子項表就應該設計外鍵。非空約束和主鍵約束基本都會加的,因為會出一些業務上的錯誤。
但是外鍵約束很多都是不加的,這個有爭議,雖然不加外鍵會造成一些冗餘數據的出現,但是實際上加了外鍵約束程序和資料庫之間會造成更多的麻煩。大多是依靠程序去檢測。另外就是索引之類的,看業務需求,如果插入數據次數多,那就不加,如果查詢的多就加上去。軟體的性能和可靠性的平衡點,這個問題不能一概而論,看你的系統需要什麼了,如果類似與銀行系統的軟體,可靠性更重要一些,而一般的互聯網產品可能更在乎用戶體驗,產品的流暢性更重要一些。
提高性能也要區分來看:是為了提高查詢性能還是插入、更新的性能。
比如唯一約束,一般可以提高查詢該欄位的性能,但是相對來說對插入和更新的性能略有影響。主鍵的約束是默認具有的,所以有些資料庫結構看不到任何顯示的約束語句,但約束是必須的
建立約束的目的是為了防止資料庫中出現不符合語義規定、不符合業務邏輯的數據,為了確保數據的完整性、合法性。如果數據具有完整性,則表示數據有效——正確並且準確、資料庫的關係結構是完整的。完整性約束可以加強資料庫的關係結構,這些規則使數據在各個表之間保持一致。
總的來說有五種約束類型:唯一性和主鍵約束、外鍵約束、檢查約束、空值約束、默認值約束,對應五大關鍵詞,UNIQUE和Primary Key, Foreign Key, CHECK, NOT NULL, DEFAULT。這五種約束類型,除檢查約束外,其餘的在前面的章節中都有過介紹,比如主鍵、外鍵欄位類型的選擇,欄位長度的設計,注釋的規範等等,在後面的命名規範中也還會提到。
檢查約束(CHECK),用於檢查列的類型和範圍,語法:CONSTRAINT [constraint_name] CHECK (condition); 比如:check(Age &>2)。過去沒有在資料庫中添加檢查約束的習慣,在本規範中,也暫不做此要求,這會增加資料庫設計過程中顧慮點,還是交由程序和前端來控制這種細節上的數據合法性。
所在團隊設定的規範中要求,除檢查約束外,其餘四種都要在資料庫中加強約束,同時,程序也會根據資料庫中約束的設置做相應處理。
主鍵不用說,一般情況下都會加約束的。要注意的是唯一欄位,比如用戶表中的電話、郵箱、登錄賬號等等明顯唯一的信息,都要加強約束,還有多對多關係中間表裡的複合主鍵,也要加強約束。再就是,前面也提到過,本規範中所有主鍵欄位統一使用UUID,char(32)類型,具體命名方式後面也會講。
外鍵部分,類型自然要和主鍵一樣統一為char(32),除了外鍵欄位,為了保存主表其它信息的擴展欄位類型也要和主表中的相應欄位類型統一。過去參與的項目中有的在資料庫中加了外鍵的強約束,有的則沒有,有的是在用PD設計時加上了主從引用關係,但在導入到庫中時去掉了外鍵的強約束,而只保留表結構。
表面看,資料庫中加上外鍵、非空、唯一等強約束會給程序編寫帶來麻煩,實則不然。約束是為了保證數據的合理性,如果資料庫設計的約束本身沒問題,那程序編寫中因約束而照成的不便就多是程序本身的不合理造成的。萬千世界,所有約束規範都是為了確保被約束規範的對象將所參與的事情做的更好,這種最終的好不是只針對某個對象的,而是針對所有參與其中的。假如某種規範不是這樣,那它本身就是不合理的;假如它是這樣的,而被約束規範的對象覺得在這種約束下做事情不便,那就是他自己做事方法的問題了,要由他自己根據規範修正。
所以強約束帶來的不便只幻象,這種不便不但不是壞事,還會倒逼程序開發更加趨於合理,修正開發中的錯誤。而不加強約束,程序可以肆無忌憚的對資料庫進行任何操作時,如果架構設計師及開發人員的經驗、技能較強還好,否則的話,程序很可能會因有意無意讀寫錯誤信息,造成針對資料庫的無效或錯誤操作,破壞掉數據的完整性、合理性。
有些情況下,加不加強約束設計者是決定不了的,比如公司有通用的許可權管理系統對所有子項目統一管理,那在設計子項目的資料庫時就不能添加和用戶相關的外鍵約束了。還有其它類似的情況:兩個項目之間有邏輯交差,但資料庫相互隔離,只能通過互相調用介面處理業務。這種情況下,如果想保證好數據的完整性準確性,只能由程序在業務邏輯層控制,必須設計開發足夠精密才能做好。
空值約束和默認值約束不再多說,在前面欄位設置中的NOT NULL子模塊講的很詳細了,只要記得設置欄位為NOT NULL、並給欄位設置默認值可以提高查詢速度、節省表空間就可以了。
添加上外鍵約束是刪除修改主鍵信息是時表之間的耦合性較高
主鍵約束這個不用討論,經過實踐得出,如果表比較少,就加上外鍵約束,如果表很多就不要加,嚴重影響響應速度,至於那個非空約束,也不要加,盡量依賴bll層的處理,不要交給資料庫處理,並且加了外鍵約束,影響表的移動,耦合性太高了.
推薦閱讀:
※你們寫軟體的時候都是用什麼神奇的IDE?
※一個簡單的功能需要多少行代碼?
※21歲神經官能症(又叫植物神經紊亂)還能從事軟體開發嗎?
※為什麼中科大這麼優秀的大學會推薦計蒜客的C語言課程? 大學不是自己就該負責教書育人嘛?