一、基礎規范
- 使用 INNODB 存儲引擎
- 表字符集使用 UTF8
- 所有表都需要添加注釋
- 單表數據量建議控制在 5000W 以內
- 不在數據庫中存儲圖⽚、文件等大數據
- 禁止在線上做數據庫壓力測試
- 禁⽌從測試、開發環境直連數據庫
二、命名規范
- 庫名表名字段名必須有固定的命名長度,12個字符以內
- 庫名、表名、字段名禁⽌止超過32個字符。須見名之意
- 庫名、表名、字段名禁⽌止使⽤用MySQL保留字
- 臨時庫、表名必須以tmp為前綴,並以⽇日期為后綴
- 備份庫、表必須以bak為前綴,並以日期為后綴
三、庫、表、字段開發設計規范
- 禁⽌使用分區表
- 拆分大字段和訪問頻率低的字段,分離冷熱數據
- 用HASH進行散表,表名后綴使用十進制數,下標從 0 開始
- 按日期時間分表需符合 YYYY[MM][DD][HH] 格式
- 采用合適的分庫分表策略。例如千庫十表、十庫百表等
- 盡可能不使用 TEXT 、 BLOB 類型
- 用 DECIMAL 代替 FLOAT 和 DOUBLE 存儲精確浮點數
- 越簡單越好:將字符轉化為數字、使用 TINYINT 來代替 ENUM 類型
- 所有字段均定義為 NOT NULL
- 使用 UNSIGNED 存儲非負整數
- INT類型固定占用 4 字節存儲
- 使用 timestamp 存儲時間
- 使用 INT UNSIGNED 存儲 IPV4
- 使用 VARBINARY 存儲大小寫敏感的變長字符串
- 禁止在數據庫中存儲明文密碼,把密碼加密后存儲
- 用好數值類型字段
- 存儲ip最好用 int 存儲而非 char(15)
- 不允許使用 ENUM
- 避免使用 NULL 字段, NULL 字段很難查詢優化,
NULL字段的索引需要額外空間,NULL字段的復合索引無效 - 少用 text/blob , varchar 的性能會比 text 高很多,實在避免不了blob,請拆表
- 數據庫中不允許存儲大文件,或者照片,可以將大對象放到磁盤上,數據庫中存儲它的路徑
四、索引規范
1、索引的數量要控制:
- 單張表中索引數量不超過5個
- 單個索引中的字段數不超過5個
- 對字符串使⽤用前綴索引,前綴索引長度不超過8個字符
- 建議優先考慮前綴索引,必要時可添加偽列並建立索引
2、主鍵准則
- 表必須有主鍵
- 不使用更新頻繁的列作為主鍵
- 盡量不選擇字符串列作為主鍵
- 不使用 UUID MD5 HASH 這些作為主鍵(數值太離散了)
- 默認使⽤非空的唯一鍵作為主鍵
- 建議選擇自增或發號器
3、重要的SQL必須被索引,比如:
- UPDATE 、 DELETE 語句的 WHERE 條件列
- ORDER BY 、 GROUPBY 、 DISTINCT 的字段
4、多表JOIN的字段注意以下
- 區分度最大的字段放在前面
- 核⼼SQL優先考慮覆蓋索引
- 避免冗余和重復索引
- 索引要綜合評估數據密度和分布以及考慮查詢和更新比例
5、索引禁忌
- 不在低基數列上建立索引,例如“性別”
- 不在索引列進行數學運算和函數運算
6、盡量不使用外鍵
- 外鍵用來保護參照完整性,可在業務端實現
- 對父表和子表的操作會相互影響,降低可用性
7、索引命名:非唯一索引必須以idx字段1字段2命名,唯一所以必須以 uniq 字段 1 字段 2 命名,索引名稱必須全部小寫
8、新建的唯一索引必須不能和主鍵重復
9、索引字段的默認值不能為 NULL ,要改為其他的 default 或者空。 NULL 非常影響索引的查詢效率
10、反復查看與表相關的SQL,符合最左前綴的特點建立索引。多條字段重復的語句,要修改語句條件字段的順序,為其建立一條聯合索引,減少索引數量
11、能使用唯一索引就要使用唯一索引,提高查詢效率
12、研發要經常使用 explain ,如果發現索引選擇性差,必須讓他們學會使用hint
五、SQL規范
- SQL語句盡可能簡單,大的SQL想辦法拆成小的SQL語句(充分利用QUERYCACHE和充分利用多核CPU)
- 事務要簡單,整個事務的時間長度不要太長
- 避免使用觸發器、函數、存儲過程
- 降低業務耦合度,為s acle out 、 sharding 留有余地
- 避免在數據庫中進⾏數學運算(MySQL不擅長數學運算和邏輯判斷)
- 不要用 SELECT * ,查詢哪幾個字段就
SELECT這幾個字段 - SQL中使用到
OR的改寫為用IN()(OR的效率沒有IN的效率高) - in里面數字的個數建議控制在 1000 以內
-
LIMIT分頁注意效率。LIMIT越大,效率越低。可以改寫 LIMIT ,比如例子改寫:SELECT id FROM t LIMIT 10000, 10; => SELECT id FROM t WHERE id > 10000 LIMIT 10;
-
使用 UNION ALL 替代 UNION
- 避免使用大表的 JOIN
- 使用 GROUP BY 分組、自動排序
- 對數據的更新要打散后批量更新,不要一次更新太多數據
- 減少與數據庫的交互次數
-
注意使用性能分析工具
SQL explain / showprofile / mySQLsla
-
SQL語句要求所有研發,SQL關鍵字全部是大寫,每個詞只允許有一個空格
- SQL語句不可以出現隱式轉換,比如 SELECT id FROM TABLE WHERE id='1'
- IN條件里面的數據數量要少,我記得應該是500個以內,要學會使用EXIST代替IN,EXIST在一些場景查詢會比IN快
- 能不用 NOT IN 就不用 NOTIN ,坑太多了。。會把空和NULL給查出來
- 在SQL語句中,禁止使用前綴是
%的LIKE - 不使用負向查詢,如 NOT IN / LIKE
- 關於分頁查詢:程序里建議合理使用分頁來提高效率
LIMIT,OFFSET較大要配合子查詢使用 - 禁止在數據庫中跑大查詢
- 使⽤預編譯語句,只傳參數,比傳遞SQL語句更高效;一次解析,多次使用;降低SQL注入概率
- 禁止使 ORDER BY RAND()
- 禁⽌單條SQL語句同時更新多個表
六、流程規范
- 所有的建表操作需要提前告知該表涉及的查詢SQL;
- 所有的建表需要確定建立哪些索引后才可以建表上線;
- 所有的改表結構、加索引操作都需要將涉及到所改表的查詢SQL發出來告知DBA等相關人員;
- 在建新表加字段之前,要求研發至少要提前3天郵件出來,給DBA們評估、優化和審核的時間
- 批量導入、導出數據必須提前通知DBA協助觀察
- 禁止在線上從庫執行后台管理和統計類查詢
- 禁止有超級權限的應用程序賬號存在
- 推廣活動或上線新功能必須提前通知DBA進⾏行流量評估
- 不在業務高峰期批量更新、查詢數據庫
