必看的數據庫使用規範

導讀: 
關於MySQL數據庫規範,相信你們多少看過一些文檔。本篇文章給你們詳細分類總結了數據庫相關規範,從庫表命名設計規範講起,到索引設計規範,後面又給出SQL編寫方面的建議。相信這些規範適用於大多數公司,也但願你們都能按照規範來使用咱們的數據庫,這樣咱們的數據庫才能發揮出更高的性能。mysql

關於庫:

  1. 【強制】庫的名稱必須控制在32個字符之內,英文一概小寫。
  2. 【強制】庫的名稱格式:業務系統名稱_子系統名。
  3. 【強制】庫名只能使用英文字母,數字,下劃線,並以英文字母開頭。
  4. 【強制】建立數據庫時必須顯式指定字符集,而且字符集只能是utf8或者utf8mb4。建立數據庫SQL舉例:Create database db1 default character set utf8;
  5. 【建議】臨時庫、表名以tmp_ 爲前綴,並以日期爲後綴,備份庫、表以 bak_ 爲前綴,並以日期爲後綴。

關於表

  1. 【強制】表和列的名稱必須控制在32個字符之內,表名只能使用字母、數字和下劃線,一概小寫。
  2. 【強制】表名要求模塊名強相關,同一模塊使用的表名儘可能使用統一前綴。
  3. 【強制】建立表時必須顯式指定字符集爲utf8或utf8mb4。
  4. 【強制】列名儘可能不用關鍵字(如type,order等)。
  5. 【強制】建立表時必須顯式指定表存儲引擎類型,如無特殊需求,一概爲InnoDB。
  6. 【強制】建表必須有comment。
  7. 【強制】對於超過100W行的大表進行alter table,必須通過DBA審覈,並在業務低峯期執行,多個alter需整合在一塊兒。
    由於alter table會產生表鎖,期間阻塞對於該表的全部寫入,對於業務可能會產生極大影響。
  8. 【建議】建表時關於主鍵:表必須有主鍵
    (1)強制要求主鍵爲id,類型爲int或bigint,且爲auto_increment 建議使用unsigned無符號型。

    (2)標識表裏每一行主體的字段不要設爲主鍵,建議設爲其餘字段如user_id,order_id等,並創建unique key索引。
    由於若是設爲主鍵且主鍵值爲隨機插入,則會致使innodb內部page分裂和大量隨機I/O,性能降低。sql

  9. 【建議】核心表(如用戶表)必須有行數據的建立時間字段create_time和最後更新時間字段update_time,便於查問題。
  10. 【建議】表中全部字段儘可能都是NOT NULL屬性,業務能夠根據須要定義DEFAULT值。
    由於使用NULL值會存在每一行都會佔用額外存儲空間、數據遷移容易出錯、聚合函數計算結果誤差等問題。
  11. 【建議】中間表用於保留中間結果集,名稱必須以tmp_ 開頭。備份表用於備份或抓取源錶快照,名稱必須以bak_開頭。中間表和備份表按期清理。
  12. 【示範】一個較爲規範的建表語句:數據庫

    CREATE TABLE user_info (
      `id` int unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主鍵',
      `user_id` bigint(11) NOT NULL COMMENT '用戶id',
      `username` varchar(45) NOT NULL COMMENT '真實姓名',
      `email` varchar(30) NOT NULL COMMENT '用戶郵箱',
      `nickname` varchar(45) NOT NULL COMMENT '暱稱',
      `birthday` date NOT NULL COMMENT '生日',
      `sex` tinyint(4) DEFAULT '0' COMMENT '性別',
      `short_introduce` varchar(150) DEFAULT NULL COMMENT '一句話介紹本身,最多50個漢字',
      `user_resume` varchar(300) NOT NULL COMMENT '用戶提交的簡歷存放地址',
      `user_register_ip` int NOT NULL COMMENT '用戶註冊時的源ip',
      `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '建立時間',
      `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改時間',
      `user_review_status` tinyint NOT NULL COMMENT '用戶資料審覈狀態,1爲經過,2爲審覈中,3爲未經過,4爲還未提交審覈',
      PRIMARY KEY (`id`),
      UNIQUE KEY `uniq_user_id` (`user_id`),
      KEY `idx_username`(`username`),
      KEY `idx_create_time_status`(`create_time`,`user_review_status`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='網站用戶基本信息'

關於索引

  1. 【強制】InnoDB表必須主鍵爲id int/bigint auto_increment,且主鍵值禁止被更新。
  2. 【強制】InnoDB和MyISAM存儲引擎表,索引類型必須爲BTREE。
  3. 【建議】主鍵的名稱以 pk_ 開頭,惟一鍵以 uniq_uk_ 開頭,普通索引以 idx_ 開頭,一概使用小寫格式,以字段的名稱或縮寫做爲後綴。
  4. 【建議】單個表上的索引個數不能超過8個。
  5. 【建議】在創建索引時,多考慮創建聯合索引,並把區分度最高的字段放在最前面。如列userid的區分度可由select count(distinct userid)計算出來。
  6. 【建議】在多表join的SQL裏,保證被驅動表的鏈接列上有索引,這樣join執行效率最高。
  7. 【建議】建表或加索引時,保證表裏互相不存在冗餘索引。
    對於MySQL來講,若是表裏已經存在key(a,b),則key(a)爲冗餘索引,須要刪除。

SQL編寫

  1. 【強制】程序端SELECT語句必須指定具體字段名稱,禁止寫成 *。
  2. 【強制】程序端insert語句指定具體字段名稱,不要寫成insert into t1 values(…)。
  3. 【強制】除靜態表或小表(100行之內),DML語句必須有where條件,且使用索引查找。
  4. 【強制】where條件裏等號左右字段類型必須一致,不然沒法利用索引。
  5. 【強制】WHERE 子句中禁止只使用全模糊的LIKE條件進行查找,必須有其餘等值或範圍查詢條件,不然沒法利用索引。
  6. 【強制】索引列不要使用函數或表達式,不然沒法利用索引。如where length(name)='Admin'或where user_id+2=10023。
  7. 【建議】insert into…values(XX),(XX),(XX).. 這裏XX的值不要超過5000個。
    值過多雖然上線很很快,但會引發主從同步延遲。
  8. 【建議】SELECT語句不要使用UNION,推薦使用UNION ALL,而且UNION子句個數限制在5個之內。
    由於union all不須要去重,節省數據庫資源,提升性能。
  9. 【強制】禁止跨db的join語句。
  10. 【建議】不建議使用子查詢,建議將子查詢SQL拆開結合程序屢次查詢,或使用join來代替子查詢。
  11. 【建議】線上環境,多表join不要超過5個表。
  12. 【建議】在多表join中,儘可能選取結果集較小的表做爲驅動表,來join其餘表。
  13. 【建議】批量操做數據時,須要控制事務處理間隔時間,進行必要的sleep。
  14. 建議】事務裏包含SQL不超過5個
    由於過長的事務會致使鎖數據較久,MySQL內部緩存、鏈接消耗過多等問題。
  15. 【建議】事務裏更新語句儘可能基於主鍵或unique key,如update … where id=XX;
    不然會產生間隙鎖,內部擴大鎖定範圍,致使系統性能降低,產生死鎖。
  16. 【建議】減小使用order by,和業務溝通能不排序就不排序,或將排序放到程序端去作。Order by、group by、distinct這些語句較爲耗費CPU,數據庫的CPU資源是極其寶貴的。
  17. 【建議】order by、group by、distinct這些SQL儘可能利用索引直接檢索出排序好的數據。如where a=1 order by b能夠利用key(a,b)。
  18. 【建議】包含了order by、group by、distinct這些查詢的語句,where條件過濾出來的結果集請保持在1000行之內,不然SQL會很慢。

公衆號.jpg

相關文章
相關標籤/搜索