數據庫使用規范
更新時間 2024-08-29 23:46:54
最近更新時間: 2024-08-29 23:46:54
分享文章
本章節會介紹Mysql數據庫的使用規范
數據庫命名規范
- 所有的數據庫對象名稱(包括庫名、表名、列名等)建議以小寫字母命名,每個單詞之間用下劃線分割。
- 所有的數據庫對象名稱禁止使用RDS for MySQL保留關鍵字。
- MySQL官方保留字與關鍵字(MySQL 8.0):
- MySQL官方保留字與關鍵字(MySQL 5.7):
- 數據庫對象的命名要能做到見名知意,并且不超過32個字符。
- 數據庫中用到的臨時表以“tmp”為前綴并以日期為后綴。
- 數據庫中用到的備份表以“bak”為前綴并以日期為后綴。
- 在不同的庫或表中,要保證所有存儲相同數據的列名和列類型必須一致。
數據庫基本設計規范
- 所有表如果沒有特殊需求,都要使用InnoDB存儲引擎。InnoDB存儲引擎支持事務、行級鎖、具有更好的恢復性、高并發下性能更強。
- 數據庫和表的字符集統一使用UTF8字符集,避免由于字符集的轉換產生亂碼。
- 所有的表和字段都需要添加注釋。使用comment從句添加表和列的備注,從設計初期維護好數據字典。
- 控制單表數據量的大小,建議表中單行長度不得超過1024字節,單表數據量控制在500萬行以內。可以采用歷史數據歸檔(常見于日志表)和分庫分表的方式控制單表數據的大小。
- 謹慎使用RDS for MySQL分區表,避免跨分區查詢,否則查詢效率會降低。分區表在邏輯上表現為一個表,但是在物理層面上將數據存儲在多個文件。
- 表中的列不要太多,盡量做到冷熱數據分離,減小表的寬度,以便在一頁內存中容納更多的行,進而減少磁盤IO,更有效的利用緩存。
- 經常一起使用的列盡量放到一個表中,避免過多的關聯操作。
- 禁止在表中建立預留字段,否則修改列的類型會導致鎖表,修改一個字段類型的成本要高于增加一個字段。
- 禁止在數據庫中存儲圖片、文件等大的二進制數據。
數據庫字段設計規范
- 控制單表字段數量,字段上限50左右。
- 優先為表中的每一列選擇符合存儲需要的最小的數據類型。優先考慮數字類型,其次為日期或二進制類型,最后是字符類型。列的字段類型越大,建立索引占據的空間就越大,導致一個頁中的索引越少,造成IO次數增加,從而影響性能。
- 整數型選擇能符合需求的最短列類型,如果為非負數,聲明需是無符號(UNSIGNED)類型。
- 每個字段盡可能具有NOT NULL屬性,int等數字類型默認值推薦給0,varchar等字符類型默認值給空字符串。
- 避免使用ENUM類型,可以用TINYINT類型替換。
- 修改ENUM值需要使用ALTER語句,ENUM類型的ORDER BY操作效率低,需要額外操作。
- 如果定義了禁止ENUM的枚舉值是數值,可使用其他數據類型(如char類型)。
- 實數類型使用DECIMAL,禁止使用FLOAT和DOUBLE類型。FLOAT和DOUBLE在存儲的時候,存在精度損失的問題,很可能在值的比較時,得到錯誤的結果。
- 使用datetime、timestamp類型來存儲時間,禁止使用字符串替代。
- 使用數字類型INT UNSIGNED存儲IP地址,用INET_ATON、INET_NTOA可以在IP地址和數字類型之間轉換。
- VARCHAR類型的長度應該盡可能短。VARCHAR類型雖然在硬盤上是動態長度的,但是在內存中占用的空間是固定的最大長度。
- 使用VARBINARY存儲大小寫敏感的變長字符串,VARBINARY默認區分?小寫,沒有字符集概念,速度快。
數據庫索引設計規范
- 每個InnoDB表強烈建議有一個主鍵,且不使用更新頻繁的列作為主鍵,不使用多列主鍵。不使用UUID、MD5、字符串列作為主鍵。最好選擇值的順序是連續增長的列作為主鍵,所以建議選擇使用自增ID列作為主鍵。
- 限制每張表上的索引數量,建議單張表索引不超過5個。索引并不是越多越好,索引可以提高查詢的效率,但會降低寫數據的效率。有時不恰當的索引還會降低查詢的效率。
- 禁止給表中的每一列都建立單獨的索引。設計良好的聯合索引比每一列上的單獨索引效率要高出很多。
- 建議在下面的列上建立索引:
- 在SELECT,UPDATE,DELETE語句的WHERE從句上的列。
- 在ORDER BY,GROUP BY,DISTINCT上的列。
- 多表JOIN的關聯列。
- 索引列順序:
- 區分度最高的放在聯合索引的最左側。區分度=列中不同值的數量/列的總行數。
- 盡量把字段長度小的列放在聯合索引的最左側。因為字段長度越小,一頁能存儲的數據量越大,IO性能也就越好。
- 使用最頻繁的列放到聯合索引的左側。這樣可以比較少的建立一些索引。
- 避免冗余的索引,如:primary key(id),index(id),unique index(id)
- 避免重復的索引,如:index(a,b,c),index(a,b),index(a),重復的和冗余的索引會降低查詢效率,因為RDS for MySQL查詢優化器會不知道該使用哪個索引。
- 在VARCHAR字段上建立索引時,需指定索引長度,沒必要對全字段建立索引,根據實際文本區分度決定索引長度即可。一般對字符串類型數據,長度為20的索引,區分度會高達90%以上,可以使用 count(distinct left(列名, 索引長度))/count(*) 的區分度來確定。
- 對于頻繁查詢優先考慮使用覆蓋索引。覆蓋索引指包含了所有查詢字段的索引,不僅僅是WHERE從句GROUP BY從句中的列,也包含SELECT查詢的列組合,避免InnoDB表進行索引的二次查詢。
- 外鍵約束:建立外鍵關系的對應列的字符集必須保持一致或者存在外鍵關系的子表父表的字符集保持一致。
數據庫SQL開發規范
- 在程序中,建議使用預編譯語句進行數據庫操作。預編譯只編譯一次,以后在該程序中就可以調用多次,比SQL效率高。
- 避免數據類型的隱式轉換,隱式轉換會導致索引失效。禁止在where從句中對列進行函數轉換和計算,會導致索引失效。
- 避免使用雙%號或前置%號的查詢條件,這樣無法利用到索引。
- 禁止在查詢中使用 select * 語句。原因如下:
- 使用 select * 會消耗更多的CPU和IP以及網絡帶寬資源。
- 使用 select * 無法使用覆蓋索引。
- 不使用 select * 可以減少表結構變更對代碼帶來的影響。
- 避免使用子查詢,子查詢會產生臨時表,臨時表沒有任何索引,數據量大時嚴重影響效率。建議把子查詢轉化成關聯查詢。
- 避免使用JOIN關聯太多的表,建議不要超過5個表的JOIN操作。需要JOIN的字段,數據類型必須絕對一致。每JOIN一個表會多占用一部分內存(由“join_buffer_size”控制),會產生臨時表操作,影響查詢效率。避免使用自然連接(natural join)。
- 盡量減少同數據庫的交互次數,數據庫更適合處理批量操作。
- 使用IN代替OR IN操作可以有效的利用索引,IN的值不要超過500個。
- 不使用反向查詢,如:NOT IN、NOT LIKE
- 禁止使用 ORDER BY RAND() 進行隨機排序。該操作會把表中所有符合條件的數據裝載到內存中進行排序,消耗大量的CPU和IO及內存資源。推薦在程序中獲取一個隨機值,然后根據隨機值從數據庫獲取數據。
- 在不需要去重的情況下,要使用UNION ALL代替UNION。UNION ALL不需要對結果集再進?行排序。
- 合并多個相同操作到一起,可以提高處理效率,數據庫更適合處理批量操作。通過批量操作減少同數據庫交互次數。
- 超過100萬行的批量寫操作,要分批多次進行操作。大批量寫操作可能會造成嚴重的主從延遲。
- 如果有ORDER BY的場景,請注意利用索引的有序性。ORDER BY最后的字段是組合索引的一部分,并且放在索引組合順序的最后。避免出現file_sort的情況,影響查詢性能。正例: where a=? and b=? order by c; ,索引:a_b_c反例:索引中有范圍查找,那么索引有序性無法利用,如: WHERE a>10 ORDER BY b; ,索引a_b無法排序。
- 盡量使用ANSI SQL標準語法進行DML操作,而不是用MySQL擴展的SQL語法。常見的MySQL擴展SQL語法有:
- REPLACE INTO
- INSERT ... ON DUPLICATE KEY UPDATE
- 不建議使用存儲過程,存儲過程難以調試和擴展,更沒有移植性。
- 不建議使用觸發器,事件調度器(event scheduler)和視圖實現業務邏輯,這些業務邏輯應該在業務層處理,避免對數據庫產生邏輯依賴。
- 不建議使用大事務,業務允許的情況下,事務里包含SQL語句越少越好,盡量不超過5個。因為過長的事務會導致鎖數據較久,以及MySQL內部緩存、連接消耗過多等問題。
- TRUNCATE TABLE比DELETE速度快,且使用的系統和日志資源少,如果刪除的表上沒有TRIGGER,且進行全表刪除,建議使用TRUNCATE TABLE。