課程准備: MySQL 5.7版本+SQLyog
數據庫設計規范
- 數據庫命名規范
所有的數據庫對象名稱必須使用小寫字母並用下划線分割(數據庫名 表名 列名...) 大小寫敏感
所有的數據庫對象名稱禁止使用MySQL保留關鍵字
所有的數據庫對象命名做到見名識義,最多不超過32個字符
例如:用戶數據庫 mc_userdb
用戶賬號表 user_account
臨時庫表必須以tmp_為前綴以日期為后綴
備份庫、備份表以bak_為前綴並以日期為后綴
所有存儲相同數據的列名和列類型必須一致
- 數據庫基本設計規范 如存儲引擎的選擇,字符集選擇
MySQL5.5使用之前Myisam(默認存儲引擎)所有表必須使用Innodb存儲引擎,(特殊需求:列存儲除外,空間數據) 5.6以后的默認Innodb存儲引擎,支持事務,行級鎖,更好的恢復性,高並發下性能更好。
數據庫和表的字符集統一使用UTF8,兼容性更好,避免亂碼。
所有表和字段都要添加注釋COMMENT,從一開始就進行數據字典的維護
盡量控制單表數據量的大小,建議控制在500萬行內,但500萬行不是MySQL數據庫的限制。過大對於修改表結構,備份,恢復都會有很大問題。MySQL沒有對存儲有限制,取決於存儲設置和文件系統。
可以使用歷史數據歸檔,分庫分表等手段來實現控制數據量大小
謹慎使用MySQL分區表
分區表在物理上表現為多個文件,在邏輯上表現為一個表
謹慎選擇分區鍵,跨區查詢效率可能更低
建議采用物理分表的方式管理大數據
盡量做到冷熱數據分離,減小表的寬帶
MySQL限制最多存儲4096列,且每行不能超過65535字節。足夠大了
減少磁盤IO,保證熱數據的內存緩存命中率
更有效的利用緩存,避免讀入無用的冷數據
經常一起使用的列放在一個表中
禁止在表中建立預留字段
其實很牽強,無法確認預留字段的數據類型
對預留字段類型進行修改,會對表進行鎖定
禁止在數據庫中存儲圖片,文件等二進制數據
使用文件服務器
禁止在線上數據庫壓力測試
禁止從開發環境,測試環境直接連生產環境數據庫
- 數據庫索引設計規范 索引列選擇的常規方式,索引優化建議及技巧
"雙刃劍"
避免建立冗余索引和重復索引
冗余:index(a,b,c) index(a,b) index(a)
限制每張表的索引數量,建議單張表索引不超過5個
索引不是越多越好!索引可以提高效率同樣也可以降低效率
索引可以增加查詢效率,但同樣也會降低插入和更新效率
禁止給表中的每一列都建立單獨的索引
Innodb是按照哪個索引的順序來組織表的呢?答案:主鍵
每個Innodb表必須有一個主鍵(或者非空唯一的字段或自動生成的但是性能不大好)
不使用更新頻繁的列作為主鍵,不能用多列做主鍵(聯合索引)
不適用UUID,MD5,HASH,字符串列作為主鍵
建議主鍵使用自增ID值
常見索引列建議:select update delete語句的where從句的列
包含order by group by distinct中的字段 組成聯合索引
多表join的關聯列
如何選擇索引列的順序:
區分度最高(重復率低)的列放在聯合索引的最左側
字段長度小的列放在聯合索引的最左側
使用最頻繁的列房到聯合索引的左側
如果一個索引包含(或覆蓋)所有需要查詢的字段的值,稱為‘覆蓋索引’。即只需掃描索引而無須回表。
盡量避免使用外鍵
不建議使用外鍵約束,但一定在表與表之間的關聯鍵上建立索引
- 數據庫字段設計規范 如何選擇列的字段類型,與性能息息相關
優先選擇符合需要的最小數據類型
比如:字符串轉數字類型存儲 INET_ACTION('255.255.255.0')=4294967295
INET_NTOA(4294967295)='255.255.255.0'
對於非負的數據來說,要優先使用無符號整型來存儲 UNSIGNED
VARCHAR(N)中的N代表的是字符數,而不是字節數
使用UTF8存儲漢字VARCHAR(255)=765個字節
過大的定義長度會消耗更多的內存
避免使用TEXT,BLOG數據類型,使用varchar()或者把BLOB或者TEXT列分離到單獨的擴展表中。
避免使用枚舉ENUM數據類型
盡可能把所有列定義為NOT NULL
由於索引NULL列需要額外的空間來保存,所以要占用更多的空間
進行比較和計算時要對null值做特別的處理
使用timestamp或者datetime存儲時間類型 timestamp更小4字節,另一個8字節但有范圍限制
財務相關的金額類數據,使用decimal數據類型(精准浮點)float和double屬於非精准浮點類型
- 數據庫SQL開發規范
避免使用雙%號 和 like
使用left join 或not exists來優化not in操作
禁止跨庫查詢 為數據遷移和分庫分表留出余地,降低耦合度,降低風險
禁止使用select *
消耗更多的cpu和io以及網絡帶寬資源
無法使用覆蓋索引
減小表結構變更帶來的影響
禁止使用不含字段列表的insert語句
insert into t values(‘a’,‘b’,‘c’);不允許
insert into t (c1,c2,c3)values(‘a’,‘b’,‘c’);
避免使用子查詢,可以把子查詢優化為join操作(一般情況);
因為子查詢的結果集無法使用索引
子查詢會產生臨時表,如果子查詢數據量大會嚴重影響效率
消耗過多的cpu以及io資源
避免使用join關聯太多的表,意見不超過5個
每join一個表多占用一部分內存(join_buffer_size)
會產生臨時表操作,影響查詢效率
減少同數據庫的交互次數
數據庫更適合批量操作
合並多個相同的操作到一起,可提高處理效率
例如:alter操作 add和change一起
使用in代替or in里的值不要超過500個
禁止使用order by rand()進行隨機排序
禁止where從句中對列進行函數轉換和計算
例如:where date(createtime)=‘20160901’ 會無法使用createtime列上索引
改成 where createtime>='20160901'
and createtime <'20160902'
盡量 union all 代替 union
拆分復雜的大SQL為多個小SQL
MySQL一個SQL只能使用一個CPU進行計算
- 數據庫操作行為規范 運維人員
對於大表修改使用pt-online-schema-change修改表結構
避免大表修改產生的主從延遲
避免在對表字段進行修改時進行鎖表
禁止為程序使用的賬號賦予super權限
對於程序連接數據庫賬號,遵循權限最小原則