1. 程式人生 > >我設計資料庫常用的幾個原則

我設計資料庫常用的幾個原則

以MySQL5.7為例,在一個專案中的資料庫schema中建表 # 〇、建庫 統一字符集和排序規則 ## 規則 庫的預設字符集選擇utf8mb4,表、欄位預設上級 庫的排序規則選擇utf8mb4_general_ci,表、欄位預設上級 ## 好處 統一排序規則,防止不必要的隱式轉換,庫級先指定,表級,欄位級預設上級即可。 # 一、命名法 如果是大小寫敏感的資料庫【MySQL】就用蛇形命名法【小寫+下劃線】 如果是大小寫不敏感的資料庫【SQL Server】就用大駝峰式【大小寫】 # 二、望文生義,自說明 百度百科中,望文生義:漢語成語,意思是指不瞭解某一詞句的確切涵義或來源緣由,光從字面上去牽強附會,做出不確切的解釋。 ## 規則 在資料庫設計中,表名欄位名一定要用有意義的名詞,即自說明,每一個名詞都是由有意義的英文或者通用英文縮寫組成。鑑別方式:使用百度搜索欄位名中的單詞,可以搜尋到,則命名沒問題。 ## 例子 公司可以使用 corporation 或者縮寫corp,不能用gongsi,下圖為搜尋縮寫的結果 ![](https://img2020.cnblogs.com/blog/40939/202011/40939-20201102102815839-1532314112.png) 數量可以使用 quantity 或者縮寫qty,不能用shuliang、numb(糟糕的選擇,單詞意義是麻木的; 失去知覺的; 遲鈍的; 呆滯的)、num。下圖為縮寫搜尋的結果 ![](https://img2020.cnblogs.com/blog/40939/202010/40939-20201031074738160-166822764.png) 注意:縮寫必須是約定俗成的,是行業通用的,否則寧可欄位過長也不要縮寫。不規範的縮寫會導致表名易用性和可維護性變差。對開發人員和維護人員極其不友好。 ## 好處 使不瞭解表結構的人,直接看錶名、欄位名就可以知道表、欄位的意義。儘量不查備註,因為檢視備註也需要花時間,對開發的編碼流暢性干擾很大。 注意: 1、欄位名要簡短、易於理解、無歧義。 2、雖然已經望文生義、自說明,但是不意味著可以省略備註,每個表和欄位還是有必要加上備註的,防止出現歧義。 # 三、欄位統一 ## 規則 意義相同的欄位就算在不同表中也要保持欄位名相同、保持型別相同。 所以備註要言簡意賅,如果不同表出現相同欄位,只要全庫搜尋備註就能找到相同意義的欄位,這樣就可以維持欄位統一 ## 好處 1、依舊是望文生義,當已經習慣於一個欄位名,該欄位在其他表中出現對開發識別字段意義有幫助 2、當兩個表的資料相互傳遞時,可以使用相同屬性名反射實現set、get方法,給開發提供便利 3、型別相同防止欄位比較時出現隱式型別轉換 # 四、模組分組 如果系統設計中劃分了模組,各模組的表名中必須加了相同的模組簡稱字首 ## 例子 字典表模組中的 ![](https://img2020.cnblogs.com/blog/40939/202010/40939-20201031074956248-347295430.png) 計量單位表dict_unit 公司表dict_corp 系統模組中的 ![](https://img2020.cnblogs.com/blog/40939/202010/40939-20201031074908594-1454172508.png) 使用者表sys_user 角色表sys_role ## 好處 相同模組的表在工具中檢視時是排列在一起的。方便查詢相關表。 # 五、主鍵名 主鍵id不能統一命名為id,有要加上表資訊,即使用者表user主鍵user_id ## 規則 不要使用統一id當主鍵名,要有修飾詞 ## 例子 使用者屬於某公司,即使用者表中需要儲存公司表的主鍵作為外來鍵【即使不建立外來鍵】 使用者表使用user,公司表使用corp 如果在公司表中主鍵id使用id,但在user表中主鍵id也是id,必然user表的外來鍵公司id 應該是corp_id,這樣會導致一個結果當user表和corp表聯結時, 聯結條件必須是user.corp_id = corp.id 如果聯結的表過多時表名使用別名a,b,u,c時極其容易寫錯,還不容易排查錯誤 而如果user表主鍵定義為user_id,corp表主鍵定義為corp_id,user表中的公司id外來鍵也定義為corp_id, 這樣當表聯結時,聯結條件寫為user.corp_id=corp.corp_id,聯結條件一目瞭然。提高了SQL的可讀性,節省了閱讀SQL時表聯結鍵的確認時間。 ## 好處 節省開發時間,就算一次節省半秒,上千次之後也會節省十分鐘,作為一個專案經理或dba,就算你做不到給開發減輕工作量,也不能拖後腿吧。 符合欄位統一原則。 # 六、儘量not null ## 規則 在設計欄位時儘量使用not null不可空。 數字型別預設0,字串型別預設''零長度的字串。 日期型別如果可以預設當前時間。 我知道作為開發人員嫌不可空麻煩,但是實際上可以在實體的getter方法中改寫 數字可以return userId ==null?0:userID; 字串可以return name ==null?"":name.trim(); 日期可以return dt==null?new DateTime(); 以上寫法可以保證你的實體在插入時肯定不空,雖然開發寫起來麻煩,但是好處多多。 ## 好處 易於優化,雖然很多開發不以為然,但是你的專案真的需要高效能時你會後悔莫及,而很多專案開始時由於開發不考慮效能導致後期優化很費勁,為什麼不提前把可以做好的做到最好。 節省空間,雖然可能只節省一個bit,但積少成多,好的效能都是一點一點積累出來的。 防止java出現空指標,好多空指標都是由於髒資料引起的。 NULL可能導致計算錯誤。例如concat(a,b),若a是NULL,結果為NULL。 如果時間欄位無法預設時間,完全可以設定為null,不要在心裡就反對null或者反對not null,我們是設計資料庫,不要出現黨*爭。 # 七、注意varchar 當欄位可以確定長度不超過一定數值時,建議使用char定長字串型別,但如果整張表已經出現變長欄位,那麼都使用變長欄位即可。 ## 規則 如果可以都使用定長字串,如果做不到就都使用變長字串 ## 好處 節省空間 易於優化 速度快,DBMS易於處理 # 八、正規化 儘量符合三正規化 ## 規則 欄位不可分割、表有主鍵、資料沒有允餘、表間關係明確 ## 好處 正規化目的是使結構更合理,消除儲存異常,使資料冗餘儘量小。便於插入、刪除和更新。 正規化是給關係型資料庫創立的。對於增刪改查四種操作總體來說效能和易用性最佳。如果你們的表只需要插入和查詢,或者只需要插入和清空,CRUD四種操作不全需要時,完全可以違反正規化。具體情況具體分析,沒有必要在心裡就反對正規化或者嚴格遵守正規化。我們是設計資料庫,不是教條主義,不要出現黨*爭。 # 九、固定欄位 刪除標誌、建立時間、修改修改、建立人id、修改人id五個欄位為必須欄位。 ## 規則 刪除標誌預設為未刪除的值, 建立時間設定為當前時間, 修改時間設定為資料修改時更新, 建立人設定id預設為0 建立人設定id預設為0 ## 好處 大部分情況,這些欄位都有必要,除非不需要保留已刪除資料的不需要刪除標識,而這種情況,基本在專案開始時分辨不出需要邏輯刪除還是物理刪除。 建立時間、修改時間、建立人、修改人沒必要解釋 # 十、狀態值 ## 規則 狀態值,儘量不使用0,一般選擇10,20,30,40等, ## 好處 防止需求突然加中間狀態,原來定義的是0,1,2,3連續的狀態,突然需要在2,3之間加個新狀態,只能使用4,這樣會對開發理解造成障礙,而如果初始就使用10,20,30,40作為狀態,突然需要在20,30之間的新狀態,完全可以使用25,即好理解又符合邏輯。 0對於前端開發不友好。 # 最後、上線前統一字符集和排序規則 專案上線之前執行以下SQL,會查詢出指定庫下的所有欄位的排序規則和字符集,一定要統一後,再上線 其他老生常談的問題可以自己查詢,比如建議使用自增列做主鍵等 select table_name,column_name,character_set_name,collation_name from information_schema.columns where table_schema = '庫名' and data_type = 'varchar' ## 好處 防止字串比較時出現隱式轉換。 # 總結、好的設計會提高效能,提升便利 在保證效能的基礎上,方便開發、易於運維、易於交接。 以上原則不是鐵律,如果有的原則導致效能急劇下降,使用很不便利,完全可以無視原則,具體情況具體分析。世界上沒有放之四海皆準的規則。