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