浅谈Mysql 表设计规范
本文首先探討下數據庫設計的三大范式,因為范式只是給出了數據庫設計的原則,并沒有告訴我們實際操作中應該怎樣操作,應該注意什么,所以我們還會談下實際工作中需要注意的具體操作問題。
三大范式
?
首先放出三大范式內容,然后再進行解釋:
第一范式:確保每列的原子性.,如果每列(或者每個屬性)都是不可再分的最小數據單元(也稱為最小的原子單元),則滿足第一范式.;(只要是關系型數據庫都滿足1NF)
第二范式:如果一個關系滿足第一范式,并且除了主鍵以外的其它列,都依賴于該主鍵,則滿足第二范式.;
第三范式:如果一個關系滿足第二范式,并且除了主鍵以外的其它列都不依賴于主鍵列,則滿足第三范式。
一范式就是屬性不可分割。屬性是什么?就是表中的字段。不可分割的意思就按字面理解就是最小單位,不能再分成更小單位了。這個字段只能是一個值,不能被拆分成多個字段。不過能不能分割并沒有絕對的答案,看需求,也就是看你的設計目標而定。
舉例:學生信息組成學生信息表,有姓名、年齡、性別、學號等信息組成。姓名不可拆分吧?所以可以作為該表的一個字段。但我要說這個表要在國外使用呢?人家姓和名要分開,都有特別的意義,所以姓名字段是可拆分的,分為姓字段和名字段。簡單來說,一范式是關系數據庫的基礎,但字段是否真的不可拆分,根據你的設計目標而定。
二范式就是要有主鍵,要求其他字段都依賴于主鍵。為什么要有主鍵?沒有主鍵就沒有唯一性,沒有唯一性在集合中就定位不到這行記錄,所以要主鍵。其他字段為什么要依賴于主鍵?因為不依賴于主鍵,就找不到他們。如果有同學不理解依賴這個詞,可以勉強用“相關”這個詞代替,也就是說其他字段必須和它們的主鍵相關。因為不相關的東西不應該放在一行記錄里。
舉例:學生信息組成學生表,姓名可以做主鍵么?不能!因為同名的話,就不唯一了,所以需要學號這樣的唯一編碼才行。那么其他字段依賴于主鍵是什么意思?就是“張三”同學的年齡和性別等字段,不能存儲別人的年齡性別,必須是他自己的,因為張三的學號信息就決定了,這行記錄歸張三所有,不能給無關人員使用。
三范式就是要消除傳遞依賴,方便理解,可以看做是“消除冗余”。消除冗余應該比較好理解一些,就是各種信息只在一個地方存儲,不出現在多張表中。比如說大學分了很多系(中文系、英語系、計算機系……),這個系別管理表信息有以下字段組成:系編號,系主任,系簡介,系架構。那么再回到學生信息表,張三同學的年齡、性別、學號都有了,我能不能把他的系編號,系主任、系簡介也一起存著?如果你問三范式,當然不行,因為三范式不同意。因為系編號,系主任、系簡介已經存在系別管理表中,你再存入學生信息表,就是冗余了。三范式中說的傳遞依賴,就出現了。這個時候學生信息表中,系主任信息是不是依賴于系編號了?而這個表的主鍵可是學號啊!所以按照三范式,處理這個問題的時候,學生表就只能增加一個系編號字段。這樣既能根據系編號找到系別信息,又避免了冗余存儲的問題。
還有要強調的就是所謂的范式,是用來學習參考的,設計的時候根據情況,未必一定要遵守。因為在數據庫數據量特別大,并且訪問并發也大的情況下,可能要采用反范式設計來提高數據庫響應速度,不過這里不在過多討論,有興趣的同學可以到這個網址查看具體內容,該文檔針對mysql的優化做了詳細說明:https://wenku.baidu.com/view/aa43ecc3aa00b52acfc7ca94.html
實際操作規范(mysql)
-
表設計
庫名、表名、字段名必須使用小寫字母,“_”分割,且名稱長度不超過12個字符并且要做到見名知意。
建議使用InnoDB存儲引擎。
存儲精確浮點數必須使用DECIMAL替代FLOAT和DOUBLE。
建議使用UNSIGNED存儲非負數值。
建議使用INT UNSIGNED存儲IPV4。
整形定義中不添加長度,比如使用INT,而不是INT(4)。
使用短數據類型,比如取值范圍為0-80時,使用TINYINT UNSIGNED。
不建議使用ENUM類型,使用TINYINT來代替。
盡可能不使用TEXT、BLOB類型。
VARCHAR(N),N表示的是字符數不是字節數,比如VARCHAR(255),可以最大可存儲255個漢字,需要根據實際的寬度來選擇N。
VARCHAR(N),N盡可能小,因為MySQL一個表中所有的VARCHAR字段最大長度是65535個字節,進行排序和創建臨時表一類的內存操作時,會使用N的長度申請內存。
表字符集選擇UTF8。
使用VARBINARY存儲變長字符串。
存儲年使用YEAR類型,存儲日期使用DATE類型,存儲時間(精確到秒)建議使用TIMESTAMP類型,因為TIMESTAMP使用4字節,DATETIME使用8個字節。
建議字段定義為NOT NULL。
將過大字段拆分到其他表中。
禁止在數據庫中使用VARBINARY、BLOB存儲圖片、文件等。
-
索引
索引名稱必須使用小寫,非唯一索引必須按照“idx_字段名稱_字段名稱[_字段名]”進行命名,唯一索引必須按照“uniq_字段名稱_字段名稱[_字段名]”進行命名。
索引中的字段數建議不超過5個。
單張表的索引數量控制在5個以內。
唯一鍵由3個以下字段組成,并且字段都是整形時,使用唯一鍵作為主鍵。
沒有唯一鍵或者唯一鍵不符合4中的條件時,使用自增(或者通過發號器獲取)id作為主鍵。
唯一鍵不和主鍵重復。
索引字段的順序需要考慮字段值去重之后的個數,個數多的放在前面。
ORDER BY,GROUP BY,DISTINCT的字段需要添加在索引的后面。
使用EXPLAIN判斷SQL語句是否合理使用索引,盡量避免extra列出現:Using File Sort,UsingTemporary。
UPDATE、DELETE語句需要根據WHERE條件添加索引。
不建議使用%前綴模糊查詢,例如LIKE “%weibo”。
對長度過長的VARCHAR字段建立索引時,添加crc32或者MD5?Hash字段,對Hash字段建立索引。
合理創建聯合索引(避免冗余),(a,b,c)相當于 (a) 、(a,b) 、(a,b,c)。
合理利用覆蓋索引。
SQL變更需要確認索引是否需要變更并通知DBA。
-
SQL語句
SQL語句中IN包含的值不應過多。
UPDATE、DELETE語句不使用LIMIT。
WHERE條件中必須使用合適的類型,避免MySQL進行隱式類型轉化。
SELECT語句只獲取需要的字段。
SELECT、INSERT語句必須顯式的指明字段名稱,不使用SELECT *,不使用INSERTINTO table。
使用SELECT column_name1, column_name2 FROM table WHERE[condition]而不是SELECT column_name1 FROM table WHERE[condition]和SELECT column_name2 FROM table WHERE [condition]。
WHERE條件中的非等值條件(IN、BETWEEN、<、<=、>、>=)會導致后面的條件使用不了索引。
避免在SQL語句進行數學運算或者函數運算,容易將業務邏輯和DB耦合在一起。
INSERT語句使用batch提交(INSERT INTO tableVALUES,,……),values的個數不應過多。
避免使用存儲過程、觸發器、函數等,容易將業務邏輯和DB耦合在一起,并且MySQL的存儲過程、觸發器、函數中存在一定的bug。
避免使用JOIN。
使用合理的SQL語句減少與數據庫的交互次數。
不使用ORDER BY RAND,使用其他方法替換。
建議使用合理的分頁方式以提高分頁的效率。
統計表中記錄數時使用COUNT(*),而不是COUNT(primary_key)和COUNT(1)。
禁止在從庫上執行后臺管理和統計類型功能的QUERY。
-
散表
每張表數據量建議控制在5000w以下。
可以結合使用hash、range、lookup table進行散表。
散表如果使用md5(或者類似的hash算法)進行散表,表名后綴使用16進制,比如user_ff。
推薦使用CRC32求余(或者類似的算術算法)進行散表,表名后綴使用數字,數字必須從0開始并等寬,比如散100張表,后綴從00-99。
使用時間散表,表名后綴必須使用特定格式,比如按日散表user_20110209、按月散表user_201102。
文:https://www.yidianzixun.com/article/0GJKj9Xz?title_sn/0&s=9&appid=xiaomi&ver=3.9.6.0&utk=4lxc4q7c
總結
以上是生活随笔為你收集整理的浅谈Mysql 表设计规范的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 现在不投新能源 就像20年前没买房?
- 下一篇: mysql rename语法错误_为什么