MySql數據庫規範整理

mysql設計規範》

數據結構設計:邏輯設計 –> 物理設計
實際工作中:邏輯設計 + 物理設計
物理設計:表名,字段名,字段類型
磁盤IO和操作系統類型,對mysql的性能是非常大的
一. 數據庫命名規範

所有的數據庫對象名稱必須使用小寫字母並用下劃線表示,因爲默認情況下,mysql對大小寫敏感,mysql數據庫本質上是linux系統下的一個文件,而linux系統是大小寫敏感的
所有數據庫對象名稱禁止使用mysql保留關鍵字
數據庫對象的命名要能做到見名知意,並且最好不要超過32個字符。太長不方便使用,並且會在傳輸時增加網絡開銷
臨時表必須以tmp_爲前綴並以日期爲後綴
備份表必須以bak_爲前綴並以日期爲後綴
所有存儲相同數據的列名和列類型必須一致,比如user表中的id和order表中的user_id
二. 數據庫基本設計規範

所有表必須使用Innodb存儲引擎 
極少數特殊業務需求除外
Innodb引擎是5.6之後的默認存儲引擎;mysql5.5之前使用Myisam(默認存儲引擎)
Innodb優點:支持事務,行級鎖,更好的恢復性,高併發下性能更好
數據庫和表的字符集統一使用UTF-8 
如果要存儲一些如表情符號的,還需使用UTF-8的拓展字符集
數據庫,表,字段字符集一定要統一,統一字符集可以避免由於字符集轉換產生的亂碼
在mysql中UTF-8字符集,漢字佔3字節,ASCII碼佔1字節
所有表和字段都需要添加註釋
從一開始就進行數據字典的維護 
即數據庫說明文檔
儘量控制單表數據量大小, 
建議控制在500萬以內,雖然500萬並不是mysql的數據庫限制,但是會給修改表結構,備份,恢復帶來很大困難。
單表可存儲數據量大小取決於存儲設置和文件系統
想減少單表數據量:歷史數據歸檔(常見於日誌表),分庫分表(常見於業務表),分區表
建議不要使用mysql分區表,因爲分區表在物理上表現爲多個文件,在邏輯上表現爲一個表。如果一定要分區,請謹慎選擇分區鍵,跨分區查詢效率比查詢大數據量的單表查詢效率更低
建議採物理分表的方式管理大數據,但是對應用程序的開發要求和複雜度更高
儘量做到冷熱數據分離,減少表的寬度(字段數) 
減少磁盤IO,保證熱數據的內存緩存命中率,更有效的利用緩存,避免讀入無用的冷數據
這樣的話,就要對錶的列進行拆分,將經常使用的列放到一個表中,可以避免過多的關聯操作,也可以提高查詢性能
禁止在表中建立預留字段 
預留字段很難做到見名知義,預留字段無法確定存儲的數據類型,後期如果修改字段類型,會對全表鎖定,嚴重影響數據庫的併發性
對目前mysql來說,修改一個字段的成本要遠遠大於增加一個字段的成本
禁止在數據庫中存儲圖片,文件等二級制數據 
這類數據如果要存,就得使用blog或者text這樣的大字段加以存儲,會影響數據庫的性能
文件這種通常所佔數據容量很大,會在短時間內造成數據庫文件的快速增長,而數據庫在讀取數據時,會進行大量的隨機IO操作,如果數據文件過大,IO操作會非常耗時,從而影響數據庫性能
正確做法是將這類數據存儲在文件服務器中,而數據庫只村存儲地址信息
禁止在線上做數據庫壓力測試 
會對正常業務造成影響,也會產生很多垃圾數據
建議建立專門的壓力測試數據庫,進行測試,然後對比測試服務器和線上服務器的硬件環境,評估線上數據庫的性能
禁止從開發環境,測試環境直連生產環境數據庫
三. 索引設計規範(Innodb中主鍵實質上是一個索引)

限制每張表上索引數量,建議單表不超過5個索引。索引並不是越多越好,可以提高查詢效率,但是會降低插入和更新的效率。甚至在一些情況下,還會降低查詢效率,因爲mysql優化器在選擇如何優化查詢時,會根據統計信息,對每一個可用索引來進行評估,以生成一個最好的執行計劃,如果同時有很多索引都可以用於查詢,就會增加mysql查詢優化器生成查詢計劃的時間。
每個Innodb表都必須有一個主鍵。Innodb是一種索引索引組織表,是指數據存儲的邏輯順序和索引的順序是相同,Innodb是按照主鍵索引的順序來組織表的,因此,每個Innodb表都必須要有一個主鍵,如果我們沒有指定主鍵,那麼Innodb會優先選擇表中第一個非空唯一索引來作爲主鍵,如果沒有這個索引,那麼Innodb會自動生成一個佔6字節的主鍵,而這個主鍵的性能並不是最好。
不使用更新頻繁的列作爲主鍵,不使用多列聯合主鍵。因爲Innodb是一種索引索引組織表,如果主鍵上的值頻繁更新,就意味着數據存儲的邏輯順序頻繁變動,必然會帶來大量的IO操作,降低數據庫性能。
不要使用uuid,md5,hash,字符串列作爲主鍵。因爲這種主鍵不能保證主鍵的值是順序增長的,如果後來的主鍵值在已有主鍵值的中間段,那麼這個主鍵插入的時候,會將所有主鍵值大於它的列都向後移。
最好選擇能保證值的順序爲順序增長的列爲主鍵。並且數據不能重複,建議用mysql自增id建立主鍵
面試問題1: 要在哪些列上建立索引? 
在select,delete,update的where從句中的列
包含在order by,group by,distinct字段中的列
多表join的關聯列:mysql對關聯操作的處理方式只有一種,那就是嵌套循環的關聯方式,所以這種操作的性能對關聯列上的索引的依賴性很大
面試問題2: 複合索引,如何選擇索引列的順序? 
從左到右的順序來使用的
區分度(列中group by的數目和此列總行數的比值趨近於1)最高的列放在聯合索引的最左側
在區分度差不多的情況下,儘量吧字段長度小的放在聯合索引的最左側,因爲同樣的行數,字段小的文件也小,讀取時IO性能更優
使用最頻繁的列放在聯合索引的左側,這樣的話,可以較少地建立索引就能滿足需求
避免建立冗餘索引和重複索引
對於頻繁的查詢優先使用覆蓋索引 
就是包含了所有查詢字段的索引,這樣可以避免Innodb表進行索引的二次查找,並可以把隨機IO變爲順序IO提高查詢效率
儘量避免使用外鍵 
mysql和別的數據庫不同,會自動在外鍵上建立索引,會降低數據庫的寫性能
建議不使用外鍵約束,但是一定要在表與表之間的關聯鍵上建立索引,雖然外鍵是爲了保證數據的完整性,但是最好在代碼中去保證。
四. 字段設計規範

優先選擇符合存儲需要的最小的數據類型 
儘量將字符串轉化爲數字類型存儲:如將ip存儲爲數字:inet_aton(‘255.255.255.255’) = 4294967295 ,反之, inet_ntoa(4294967295) = ‘255.255.255.255’
對於非負整型數據,優先使用無符號整型來存儲,如:id,age,無符號相對於有符號,可以多出一倍的存儲空間
mysql中,varchar(n)中n表示字符數而不是字節數
避免使用text,blog來存儲字段,這種類型只能使用前綴索引,如果非要使用,建議將這種數據分離到單獨的拓展表中
避免使用enum類型。枚舉本身是一個字符串類型,但是內部確是用正數類型來存儲的,所以最多可存儲65535種不同的值,修改的話必須使用alter語句,直接修改元數據,有操作風險;order by效率低,必須轉換並無法使用索引,禁止使用數值作爲enum值,因爲enum本身是索引順序存儲的,會造成邏輯混淆
儘可能把所有列定義爲not null。 
索引null列需要額外的空間來保存,佔更多空間
進行比較和計算時,對null值作特別的處理,可能造成索引失效
禁止使用字符串來存儲日期型數據。 
無法使用日期函數計算比較
字符串存儲要佔更多的內存空間,datetime(8字節)和timestamp(本身是以int存儲,佔4字節,範圍:1970-01-01 00:00:01到2038-01-19 03:14:07)
財務相關數據,使用decimal類型 (精準浮點類型,在計算時不丟失精度)。
五. SQL開發規範

建議使用預編譯語句(prepareStatment)進行數據庫操作 
可以同步執行預編譯計劃,減少預編譯時間
可以有效避免動態sql帶來的SQL注入的問題
只傳參數,一次解析,多次使用,比傳遞sql語句更高效
避免數據類型的隱式轉換 
一般出現在where從句中,會導致索引失效,如:select id,name from user where id = ‘12’;
充分利用已存在的索引 
避免使用雙%的查詢條件,不走索引
一個SQL只能利用到複合索引中的一列進行範圍查詢
使用left join或not exists來優化not in操作
程序連接不同的數據庫使用不同的賬號,禁止跨庫查詢 
爲數據庫遷移和分庫分表留出餘地
降低業務耦合度
避免權限過大而產生的安全風險
禁止使用select * 來查詢,必須用字段名 
可能會消耗更多的cpu和IO以及網絡資源
無法使用覆蓋索引
可以減少表結構變更對已有程序的影響
禁止使用不含字段列表的insert語句。 
可以減少表結構變更對已有程序的影響
禁止使用子查詢 
雖然可使sql可讀性好,但是缺點遠遠大於優點
子查詢返回的結果集無法使用索引,結果集會被存儲到一個臨時表中,結果集越大性能越低
把子查詢優化爲join操作,但是並不是所有的都可以優化爲join,一般情況下,只有當子查詢是在in字句中,並且子查詢是一個簡單的sql(不包含union,group by,order by,limit)才能轉換爲關聯查詢
避免join過多的表 
每join一個表會佔一部分內存(join_buffer_size)
會產生臨時表操作,影響查詢效率
mysql最多允許關聯61個表,建議不超過5個
減少同數據庫的交互次數 
數據庫更適合處理批量操作
合併多個相同的操作到一起,提高處理效率
使用in代替or 
in的值不要超過500個
in 操作可以有效利用索引
禁止使用order by rand()進行隨機排序 
會把表中所有符合條件的數據裝載到內存中進行排序
會消耗大量的cpu和io及內存資源
推薦在程序中獲取隨機值
禁止在where從句中對列進行函數轉換和計算 
導致無法使用相關列上的索引
where date(create_time)=’20170901’ 寫成 where create_time >= ‘20170901’ and create_time < ‘20170902’
在明顯不會有重複值時使用union all而不是union 
union 會把所有數據放在臨時表中後再進行去重操作,會多消耗內存,IO,網絡資源
union all 不會再對結果集進行去重操作
拆分複雜的大sql爲多個小sql 
目前mysql中一個sql只能使用一個cpu計算,不支持多cpu並行計算
sql拆分後可以通過並行執行來提高處理效率
六. 數據庫操作行爲規範

主要面向手動操作數據庫的行爲 
超過100萬的批量寫操作,要分批多次進行操作 
主從複製中:大批量操作可能會造成嚴重的主從延遲,因爲當主庫執行完成後,纔會在從庫執行
binlog日誌爲row格式時會產生大量的日誌
避免產生大量事務,產生阻塞,佔滿可用連接
對大表數據結構的修改一定要謹慎 
可能會造成嚴重的鎖表操作,尤其是生產環境,是不能忍受的
對於大表使用pt-online-schema-change修改表結構:
首先會建立一個與原表結構相同的新表
然後在新表上進行表結構的修改
然後把原表中的數據複製到新表中,並且增加一些觸發器,以便把原表中即時新增的數據也複製到新表中
在行的所有數據複製完成之後,會在原表上增加一個很準的時間鎖,同時把新表命名爲原表,把原表刪掉
[實際上是把一個原子的DDL操作分解成多批次進行]
[避免大表修改產生的主從延遲問題]
[避免在對錶字段進行修改時進行鎖表]
禁止爲程序使用的賬號賦予super權限 
當數據庫連接數達到最大限制時,允許1個有super權限的用戶連接
super權限只能留給DBA處理問題的賬號使用
對於程序連接數據庫賬號,遵循權限最小原則 
程序使用的數據庫賬號只能在一個DB下使用,不準跨庫
程序使用的賬號原則上不準有drop權限
--------------------- 
作者:三呆子 
來源:CSDN 
原文:https://blog.csdn.net/xu_san_duo/article/details/78832884 
版權聲明:本文爲博主原創文章,轉載請附上博文鏈接!

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