數據庫設計以及優化

數據庫設計規範

1.數據庫命名規範

  • 規範:數據庫對象名稱(數據庫名、表名、列名等)必須使用小寫字母並用下劃線分割
    說明:Linux系統大小寫敏感,因此MySQL也是大小寫敏感。爲了避免混淆,統一使用小寫。
  • 規範:所有數據庫對象名稱禁止使用MySQL保留關鍵字。
    說明:會產生SQL語法錯誤,比如select id,from from user;(from爲關鍵字),解決方法是把from字段用反引號(鍵盤上數字1鍵的左邊那個鍵`)括起來:
select id,`from` from user;

爲了避免不必要的麻煩,請不要使用保留關鍵字作爲數據庫對象名稱。MySQL關鍵字可以使用https://dev.mysql.com/doc/refman/5.7/en/keywords.html查詢。

  • 規範:數據庫對象的命名要做到見名知意,並且最好不要超過32個字符。
    說明:32個字符不是MySQL本身限制的長度,但是命名太長在使用過程中很不方便,也會增加網絡傳輸的開銷。
    如:tb_userdb,tb=淘寶,user=用戶,db=數據庫,表示爲淘寶網的用戶數據庫;user_account,user=用戶,account=賬號,表示用戶數據庫下的賬號表
  • 規範:臨時庫表必須以tmp爲前綴並以日期爲後綴。
    說明:tmp表示臨時,日期爲後綴是爲了方便後續管理,比如根據時間清理臨時庫表。
  • 規範:備份庫、表必須以bak爲前綴並以日期爲後綴。
    說明:bak表示備份,日期爲後綴是爲了方便後續管理,比如根據恢復、清理備份庫表。
  • 規範:所有存儲相同數據的列名和列類型必須一致。
    說明: 如下,user_id存在於2個表中,名稱一致,類型一致。
    這種列(存儲相同數據的列)一般是關聯列,對查詢性能有很大影響。如果2個表的關聯列數據類型不一致,則在關聯時會進行隱式類型轉換,會造成列上的索引失效,使得查詢效率大幅度變低。
create table user(
user_id unsigned int unsigned auto_increment not null,
……
)
create table order(
order_id int primary key auto_increment,
user_id int unsigned not null,
)

2.數據庫基本設計規範

  • 規範:所有表必須使用Innodb存儲引擎。
    說明:一般使用Innodb存儲引擎,除非它無法滿足特殊需求,比如列存儲等。
    5.6之後,Innodb爲默認存儲引擎;
    支持事務,行級鎖,更好的恢復性,高併發下性能更好;
    等等。
  • 規範:數據庫和表的字符集統一使用UTF8。
    說明:UTF8兼容性好。不是說一定要用UTF8,只是說要“統一”,避免亂碼。
    如果編碼不統一,在數據庫遷移時會造成很多問題,在進行字符比較時會先轉碼從而使索引失效造成性能下降。
    MySQL中UTF8字符集漢字佔3個字節,ASCII碼佔1個字節。
  • 規範:所有表和字段都需要添加註釋。
    說明:使用comment從句添加備註,爲了從一開始就進行數據字典的維護。
CREATE TABLE `user` (
	`name` VARCHAR(50) NOT NULL COMMENT '用戶姓名',
	……
)
COMMENT='用戶表'
ENGINE=InnoDB
;

  • 規範:儘量控制單表數據量的大小,建議控制在500萬行以內。
    說明:
    500萬行不是MySQL數據庫的限制。
    單表數據量過大,對查詢性能、修改表結構、備份、恢復都有很大影響。
    MySQL可以存儲的數據量限制取決於存儲設置和文件系統:32位對單文件大小有限制。
    如何控制單表數據量:歷史數據歸檔(日誌數據)、分庫分表(業務數據)等手段。
  • 規範:謹慎使用MySQL分區表。
    說明:
    分區表在物理上表現爲多個文件,在邏輯上表現爲一個表。
    使用分區表能更好的提高性能,是有條件的,最好的情況是:分區表的不同分區文件可以存儲在不同的磁盤陣列上。
    謹慎選擇分區鍵。
    避免跨分區查詢,因爲這樣效率可能更低。
    因此建議採用物理分表而不是分區表的方式來管理大數據。
  • 規範:儘量做到冷熱數據分離,減少表的寬度。
    說明:
    MySQL對列的寬度限制4096列,每一行數據限制爲65535個字節。
    好處: 爲了減少磁盤IO,保證熱數據的內存緩存命中率; 更有效的利用緩存,避免讀入無用的冷數據。
    經常一起使用的列放到一個表中。
  • 規範:禁止在表中建立預留字段。
    說明:
    預留字段的命名很難做到見名知意。
    無法選擇合適的存儲數據類型給預留字段。因此預留字段大部分使用varchar(幾乎能存儲任何類型的數據),但是這樣的話,會降低數據庫性能。
    雖然字段名稱容易修改,但是,對預留字段類型的修改,會對錶進行鎖定,嚴重影響數據庫併發性。
    (修改一個字段類型的成本,遠大於新增一個字段)
  • 規範:禁止在數據庫中存儲圖片、文件等二進制數據。
    說明:
    存儲二進制數據一般用BLOB等大的類型,會影響性能。
    圖片等二進制數據通常很大,會短時間內讓數據庫文件大小快速增長。
    數據讀取時會很耗時。
    因此要把二進制文件存放在文件服務器上,數據庫只存儲文件路徑。
  • 規範:禁止在線上做數據庫壓力測試。
    說明:影響正常業務訪問;產生大量垃圾數據;
  • 規範:禁止從開發環境、測試環境直連生產環境數據庫。
    說明:容易誤操作破壞生產數據的完整性。

3.數據庫索引設計規範

  • 規範:限制每張表上的索引數量,建議單張表的索引不超過5個。
    說明:
    索引不是越多越好。
    索引可以增加查詢效率,但是會降低插入和更新的效率,某些情況還會降低查詢效率。
  • 規範:每個Innodb表必須有一個主鍵。
    說明:Innodb是按照主鍵索引的順序來組織表的,因此每個Innodb表都必須要有一個主鍵。
    不使用更新頻繁的列作爲主鍵(頻繁更新主鍵意味着數據存儲的邏輯順序會頻繁變動)。
    不使用多列主鍵。
    不使用UUID,MD5,HASH,字符串列作爲主鍵(無法保證主鍵索引順序增長,構建索引時爲保證索引順序,會移動大量數據)。
    建議使用自增長id。
    常見索引列建議:
  • 規範:select,update,delete語句的where從句中的列作爲索引;
  • 規範:包含在order by、group by、distinct中的字段作爲索引;
  • 規範:多表join的關聯列作爲索引。
    選擇索引列的順序:(從左到右的順序來使用的)
    區分度最高的列放在聯合索引的最左側;(區分度:select COUNT(DISTINCT column_name)/COUNT(*) from table_name)
    儘量把字段長度小的列放在聯合索引的最左側;
    使用最頻繁的列放在聯合索引的左側;
  • 規範:避免建立冗餘索引和重複索引。
    說明:
    因爲會增加生成查詢計劃的時間。
    重複索引如primary key(id),index(id),unique index(id)。
    冗餘索引如index(a,b,c),index(a,b),index(a)。
  • 規範:對於頻繁的查詢優先考慮使用覆蓋索引。
    說明:
    覆蓋索引:包含了所有查詢字段的索引。
    好處:避免Innodb表進行索引的二次查找;可以把隨機IO變爲順序IO加快查詢效率。
  • 規範:儘量避免使用外鍵。
    說明:儘量避免使用外鍵約束(寫操作效率低,數據完整性建議在業務端實現),但是要在關聯鍵加索引。

4.數據庫字段設計規範

(待更新)

5.數據庫SQL開發規範

(待更新)

6.數據庫操作行爲規範

(待更新)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章