[LNMP]Mysql數(shù)據(jù)庫設(shè)計建議

說明


本規(guī)范適用于mysql 5.1或以上版本使用

數(shù)據(jù)庫范式


  1. 第一范式(1NF)確保每列保持原子性

第一范式(1NF):數(shù)據(jù)庫表的每一列都是不可分割的原子數(shù)據(jù)項,而不能是集合,數(shù)組,記錄等非原子數(shù)據(jù)項。
<pre>
例如:
體重是每個學(xué)生的屬性,在數(shù)據(jù)庫設(shè)計的時候,不會將“體重”拆分成兩個字段保存,所以建立一個“學(xué)生表”(學(xué)生ID、姓名、身高、體重);
</pre>

  1. 第二范式(2NF)確保表中的每列都和主鍵相關(guān)

滿足第二范式(2NF)必須先滿足第一范式(1NF),第二范式(2NF)要求實體的屬性完全依賴于主關(guān)鍵字。如果存在不完全依賴,那么這個屬性和主關(guān)鍵字的這一部分應(yīng)該分離出來形成一個新的實體,新實體與原實體之間是一對多的關(guān)系。
<pre>
例如:
每個學(xué)生要選課(包含課程名、任課老師、學(xué)分),如果都放到“學(xué)生表”中,如果課程沒學(xué)生選,那找不到課程的信息,如果學(xué)生沒選
課,也找不到任何學(xué)生的信息,原因:
a. 課程、任課老師、學(xué)分 這三個信息 不是與主鍵“學(xué)生ID”相關(guān),所以應(yīng)該分離出來,形成“課程表”(課程ID、課程名、任課老師、學(xué)分),
b. 再通過一對多的方式關(guān)聯(lián)起來;
</pre>

  1. 第三范式(3NF)確保每列都和主鍵列直接相關(guān),而不是間接相關(guān)

滿足第三范式(3NF)必須先滿足第二范式(2NF),要求一個關(guān)系中不包含已在其它關(guān)系已包含的非主關(guān)鍵字信息.
<pre>
例如:仍然是上面的例子,每一行數(shù)據(jù)是:學(xué)生ID、姓名、身高、體重、課程ID
如果將“課程名”也放到記錄中,則違反了第三范式,因為“課程名”已經(jīng)包含在 學(xué)生ID與課程ID 的一對多關(guān)系中,在實際紀錄中,“課程名”將會出現(xiàn)冗余。
</pre>

范式的使用


一般情況下要求數(shù)據(jù)庫的設(shè)計符合以上三大范式,如果有特殊的需求,可以不滿足或部分滿足第3范式,但至少滿足前面兩個范式進行數(shù)據(jù)庫設(shè)計。

  1. 范式的使用可以消除數(shù)據(jù)庫的冗余,不必要的冗余除了導(dǎo)致存儲空間浪費以外,也可能導(dǎo)致檢索性能低下;
  2. 如果有違背范式的使用,需要在數(shù)據(jù)庫設(shè)計文檔中注明,方便開發(fā)人員做相應(yīng)的開發(fā)(通常是數(shù)據(jù)一致性);
  3. 恰當(dāng)?shù)娜哂嗫梢蕴嵘龣z索性能,但一定要注意數(shù)據(jù)一致性和業(yè)務(wù)場景,如果可以選擇,緩存應(yīng)該首選考慮,而不是去冗余數(shù)據(jù);
  4. 數(shù)據(jù)一致性的處理成本比想象要高

基本規(guī)范


校對編碼
  1. 一般情況下,數(shù)據(jù)庫和數(shù)據(jù)表 使用utf8_general_ci (mysql 5.5以上應(yīng)該用utf8mb4)校對編碼,注意 ci 是表示大小寫不敏感,如果需要大小寫敏感的,不使用帶 ci 結(jié)尾的字符集;
  2. 字段的校對編碼取決于具體的業(yè)務(wù)需求;
存儲引擎
  1. 一般的業(yè)務(wù)數(shù)據(jù),使用InnoDB存儲引擎,不再使用MyISAM;
  2. 內(nèi)存型數(shù)據(jù)使用 MEMORY存儲引擎,注意內(nèi)存空間配置;
類型

在滿足業(yè)務(wù)需求的前提下,選擇準確而且小的類型:

  1. 根據(jù)業(yè)務(wù)需求選擇對應(yīng)字段類型,比如人的年齡,應(yīng)該使用 TINYINT,而不是 VARCHAR
  2. 根據(jù)業(yè)務(wù)需求設(shè)置最小有效范圍(盡可能小),比如,年齡字段 就沒有必要用 INT 保存,而是用 TINYINT
  3. 如果是正整數(shù),則使用 無符號(UNSIGNED) 類型,比如:主鍵的自增字段
  4. 如果是非空的字段,設(shè)置一個合理默認的值,比如年齡設(shè)置默認值為 0
  5. 所有的字段和表,必須有注釋,說明表和字段的含義

命名規(guī)范


  1. 命名可以由 小寫字母、數(shù)字、下劃線 組成,非特殊情況,不使用大寫拼寫;
  2. 使用英文拼寫,不使用拼音拼寫;
數(shù)據(jù)庫和表命名
  1. 數(shù)據(jù)庫名以一個或多個單詞組成,用下劃線進行分隔,單詞數(shù)不超過2個,例如:wechat_feedback
  2. 數(shù)據(jù)庫前綴,以數(shù)據(jù)庫名的單詞首字母+下劃線 組成,例如 wechat_feedback 數(shù)據(jù)庫的表前綴是 wf_
  3. 表名,以前綴+詞組/單詞組成,詞組單詞數(shù)不超過3個,單詞之間不分隔,例如:wf_userinformation
字段名
  1. 字段前綴以表名(不含前綴)的單詞首字母+下劃線組成,例如,wf_userinformation 表的字段前綴是 ui_
  2. 字段名以 字段前綴+詞組/單詞組成,詞組單詞數(shù)不超過3個,單詞之間不分隔,例如:wf_userinformation 表的姓名字段:ui_name

索引約束


  1. 根據(jù)查詢需求建索引,而不是盲目地去建索引,每個索引都必須有對應(yīng)的查詢場景,否則不應(yīng)該建這個索引;
  2. 越簡單的數(shù)據(jù)類型越好,比如整型、日期型,盡量避免對字符型做索引,如果需要,則須慎重考慮(是否有替代方案);
  3. 越小的數(shù)據(jù),數(shù)據(jù)越小,存儲和內(nèi)存開銷越小,速度更快(對應(yīng)“ 基本規(guī)范:類型”)
  4. 區(qū)分度越大的字段,索引效果越好(區(qū)分度,即查詢出來的結(jié)果集的大小,區(qū)分度越大,查詢出來的結(jié)果集越小,也就是更精確);
  5. 盡量避免NULL,應(yīng)該指定列為NOT NULL,建議使用0、一個特殊的值或者一個空字符串代替。
最左前綴

InnoDB使用的B-Tree索引,在使用組合索引(多條件查詢)的時候,索引的順序很總要,要遵循的原則是:最左前綴原則
<pre>
最左前綴:在查詢條件中,MySQL只能對索引最左邊的前綴進行有效的查找。
舉例:在索引 search_index(t1,t2)中
SELECT * FORM wf_userinformation WHERE t1 = 1 AND t2 =2 (可以使用到索引 search_index)
SELECT * FORM wf_userinformation WHERE t1 = 1 (可以使用到索引 search_index)
SELECT * FORM wf_userinformation WHERE t2 = 2 (不能用到 索引 search_index)
</pre>

  1. 數(shù)據(jù)庫設(shè)計和不能僅僅自身設(shè)計,更應(yīng)該考慮查詢的場景(包括使用的查詢字段和查詢順序)
  2. 在多條件查詢(組合索引),應(yīng)該通過小結(jié)果集驅(qū)動大結(jié)果集(即將區(qū)分度大的字段放在前面,區(qū)分度小的放在后面)
  3. 將索引的情況寫入文檔,方便后面開發(fā)人員的使用或調(diào)整

通過explain做優(yōu)化


待補充...

2014/12

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容