如何更規範化使用MySQL

来源:https://www.cnblogs.com/taojietaoge/archive/2019/09/22/11533693.html
-Advertisement-
Play Games

如何更規範化使用MySQL 背景:一個平臺或系統隨著時間的推移和用戶量的增多,資料庫操作往往會變慢;而在Java應用開發中資料庫更是尤為重要,絕大多數情況下資料庫的性能決定了程式的性能,如若前期埋下的坑越多到後期資料庫就會成為整個系統的瓶頸;因此,更規範化的使用MySQL在開發中是不可或缺的。 一、 ...


如何更規範化使用MySQL

 

背景:一個平臺或系統隨著時間的推移和用戶量的增多,資料庫操作往往會變慢;而在Java應用開發中資料庫更是尤為重要,絕大多數情況下資料庫的性能決定了程式的性能,如若前期埋下的坑越多到後期資料庫就會成為整個系統的瓶頸;因此,更規範化的使用MySQL在開發中是不可或缺的。

一、MySQL資料庫命名規範

1、資料庫所有表首碼均使用項目名稱首字母縮寫;

2、資料庫所有對象名稱均使用小寫字母,並且單詞之間通過下劃線分開;

3、資料庫所有對象名稱禁止使用MySQL保留字及關鍵字,涉及到關鍵字的SQL查詢需要將關鍵字用單引號括起來;

4、資料庫所有對象名稱不超過32個字元,並且命名要遵循見名知意原則;

5、資料庫臨時表必須以 pro_tmp_ 為首碼並且以日期 _20190917 為尾碼,備份表必須以 pro_bac_ 為首碼並以時間戳為尾碼;(pro為項目名稱首字母縮寫)

6、資料庫所有存儲相同數據的列名和列類型必須保持一致。

二、MySQL資料庫基本設計規範

1、若無特殊說明,建表時一律採用Innodb存儲引擎。

      選擇合適的引擎可以提高資料庫性能,如InnoDB和MyISAM,InnoDB和MyISAM是許多人在使用MySQL時最常用的兩個表類型,這兩個表類型各有優劣,視具體應用而定;基本的差別為:MyISAM類型不支持事務處理等高級處理,而InnoDB類型支持;MyISAM類型的表強調的是性能,其執行數度比InnoDB類型更快,但是不提供事務支持,而InnoDB提供事務支持以及外部鍵等高級資料庫功能;因此,其支持事務處理、支持外鍵、支持崩潰修複能力和併發控制是我們建表時首選的存儲引擎。

2、資料庫和表的字元集統一使用UTF8

      資料庫和表的字元集統一使用utf8,若是有欄位需要存儲emoji表情之類的,則將表或欄位設置成utf8mb4;因為,utf8號稱萬國碼,其無需轉碼、無亂碼風險且節省空間,而utf8mb4又向下相容utf8。

3、設計資料庫時所有表和欄位必須添加註釋

      使用Comment從句添加表和列的備註,或直接在資料庫連接工具的註釋欄添加註釋,從項目開始就進行數據字典的維護。

使用Comment從句添加註釋如:

   1、創建表:
  CREATE TABLE t1(id varchar2(32) primary key,name VARCHAR2(8) NOT NULL,age number);
  2、添加表註釋:
  Comment on table t1 is '個人信息';
  3、添加欄位註釋:
  comment on column t1.id is 'id';
  comment on column t1.nameis '姓名';
  comment on column t1.age is '年齡'; 

使用資料庫連接工具添加註釋:

圖1. 資料庫連接工具添加註釋

 

4、單個表的數據量大小控制在500萬以內

      儘量控制單表數據量的大小,建議控制在500萬以內;500萬並不是MySQL資料庫的極限,但數據量太多不利於對錶結構進行修改、備份和恢複數據,適當採用分庫分表等手段來控制單表數據量的大小。

5、使用MySQL分區表需謹慎

      分區是將一個表的數據按照某種方式,比如按照時間上的月份,分成多個較小的,更容易管理的部分,但是邏輯上仍是一個表;分區表在物理上表現為多個文件,在邏輯上仍表現為同一個表,需要謹慎選擇分區鍵;跨分區查詢效率可能會更低,建議使用物理分區表等方式管理大數據。

6、儘量滿足冷熱數據分離,減小表等寬度

      MySQL限制每個表最多存儲4096列,並且每一行數據的大小不超過65535位元組,為了減少磁碟IO線程的開銷,就要適當控製表的寬度,因為表越寬,把表裝載進記憶體緩衝池時所占用的記憶體也就越大,就會消耗更多的IO線程;除此之外,為了保證熱數據的記憶體緩存命中率,更有效的利用緩存,避免讀入無用的冷數據,儘量把經常使用到的列放到同一個表中,避免不必要的關聯操作。

7、建立預留欄位需謹慎

      部分友人在設計資料庫表時,不僅設計了當前所需要的欄位,而且還在其中留出幾個欄位作為備用。比方說,我設計了一個人員表(Person),其中已經添加了各種必要的欄位,包括姓名(Name)、性別(Sex)、出生年月日(birthday)等等;為了以防萬一,比如之後可能Person 表會涉及到畢業院校、工作單位、是否婚配和相片等信息,於是就加入5個varchar2 型的欄位,分別叫做Text1、Text2……Text5;這一手操作看似防範於未然,其實也並不見得,因為大量預留欄位會浪費空間、預留欄位不能做到見名知意、預留欄位無法確認存儲的數據類型且修改其欄位類型還可能會造成鎖表等問題。

針對此等情況可以參考以下兩點解決方案:

1. 如果數量很少,而且信息的性質與原表密切相關,那麼就可以直接在原表上增加欄位,並將相關的數據更新進去;
2. 如果數量較大,或者並非是原表對象至關重要的屬性,那麼就可以新增一個表,然後通過鍵值連接起來;

8、資料庫中禁止存儲圖片、文件等大的二進位數據

      若往資料庫表中存儲文件,而文件通常很大,當資料庫進行讀取操作時,會進行大量的隨機IO操作,大文件使得IO操作很耗時耗性能,造成短時間內數據量快速增長;所以,通常將圖片、文件存儲在文件伺服器中,資料庫只用於存儲文件地址信息。

三、MySQL資料庫欄位設計規範

1、優先選擇符合存儲需要的最小的數據類型。

      主要是考慮索引的性能,因為列的欄位越大,建立索引時所需要的空間也越大,這樣一頁中能存儲的索引節點的數量也就越少,在遍歷時需要的IO次數也就越多,索引的性能也就越差。

2、避免使用TEXT、BLOB數據類型

      避免使用TEXT和BLOB數據類型,其中最常見的TEXT類型可以存儲64K數據,MySQL記憶體臨時表不支持TEXT、BLOB這樣的大數據類型,若查詢中包含這樣的數據,在執行排序等操作時就不能使用記憶體臨時表,必須使用磁碟臨時表執行操作;TEXT和BLOB類型只能使用首碼索引(當索引是很長的字元序列時,這個索引將會很占記憶體,而且會很慢,這時候就會用到首碼索引了;所謂的首碼索引就是去索引的前面幾個字母作為索引,但是要降低索引的重覆率,所以我們還必須要判斷首碼索引的重覆率;),因為MySQL對索引欄位長度是有限的,所以TEXT類型只能使用首碼索引,並且TEXT列上是不能有預設值的;若需要使用,建議把BLOB或TEXT列分離到單獨的的擴展表中,且查詢時一定不要使用select * ,只需取出必要的列即可。

3、避免使用ENUM枚舉類型

修改ENUM 值需要使用ALTER 語句;

ENUM 類型的ORDER BY 操作效率低;

禁止使用數值作為ENUM 的枚舉值。

4、所有列的預設值定義為NOT NULL

資料庫所有為NULL 的列需要額外的空間來存儲,因此會占用更多的空間;

資料庫在進行比較和計算時需要對NULL 值做特別處理。

5、使用TIMESTAMP(4位元組)或DATETIME(8位元組)類型存儲時間

TIMESTAMP 存儲的時間範圍為: 1970-01-01 00:00:01 ~ 2038-01-19-03:14:07;

TIMESTAMP 占用4位元組和INT相同,但可讀性比INT 類型的高,若是超出TIMESTAMP 取值範圍的則使用DATETIME 類型存儲;

用字元串類型存儲時間的缺點:無法使用日期函數進行比較計算、字元串存儲占有更多的空間。

6、財務相關的金額類數據必須使用decimal 類型

精準浮點:decimal

非精準浮點:float、double

Decimal類型為精準浮點數,在計算時不會丟失精度;占有空間大小由定義的寬度決定,每4個位元組可以存儲9位數字,且小數點也要占有一個位元組;另外,Decimal類型可用於存儲比bigint更大的數據類型。

四、MySQL索引設計規範

1、每張表的索引數量不超過5個

      索引可以增加查詢效率,但同樣也會降低插入和更新的效率,甚至有些情況下還會降低查詢效率,因此並不是越多越好,要控制其數量。

2、每個Innodb 表必須有一個主鍵

Innodb 是一種索引組織表,其數據存儲的邏輯順序和索引的順序是相同的;

每張表可以有多個索引,但表的存儲順序只能有一種,Innodb 是按照主鍵索引的順序來組織表的,因此不要使用更新頻繁的列、UUID、MD5、HASH和字元串列作為主鍵,這些列無法保證數據的順序增長,主鍵建議使用自增ID 值。

3、儘量避免使用外鍵約束

不建議使用外鍵約束(foreign key),但一定要在表與表之間的關聯鍵上建立索引;

外鍵雖然可以保證數據的參照完整性,但外鍵也會影響父表和子表的寫操作從而降低性能,還會使得表更耦合,建議在業務端實現。

五、MySQL資料庫SQL開發規範

1、建議使用預編譯語句進行資料庫操作

      預編譯語句可以重覆使用,相同的SQL語句可以一次解析,多次使用,減少SQL編譯所需要的時間,提高處理效率;此外,還可以有效解決動態SQL帶來的SQL註入問題。

2、避免數據類型的隱式轉換

      隱式轉換如:SELECT 1 + "1";數值型 + 字元型 的隱式轉換有可能會導致索引失效,以及一些意想不到的結果等。

3、充分利用表中存在的索引

1)避免使用雙%號的查詢條件

      如 WHERE first_name like '%James%',若無前置%,只有後置%,則執行SQL語句時會用到列上的索引,雙%號則不會使用列上的索引。

2)一條SQL語句只能使用複合索引中的一列進行範圍查詢

      例如有weight、age、sex三列的聯合索引,在查詢條件中有weight列的範圍查詢,則在age和sex列上的索引將不會被使用;因此,在定義聯合索引時,若某列需要用到範圍查詢,則將該列放到聯合索引的右側。

3)使用not exists 代替not in

      因為not in 在SQL語句中執行時會導致索引失效。

4、杜絕使用SELECT * ,必須使用SELECT <欄位列表> 查詢

      因為使用SELECT * 查詢會消耗更多的CPU、IO和網路寬頻資源,並且查詢時無法使用覆蓋索引。

5、禁止使用不含欄位列表的INSERT 語句

      如:INSERT into table_name values ('1','2','3'); 改為帶欄位列表的INSERT 語句:INSERT into table_name('c1','c2','c3') values ('1','2','3');

6、避免使用子查詢,可以把子查詢優化為join 關聯操作

但是,通常子查詢在in 子句中,且子查詢中為簡單SQL(即不包含union、group by、order by、limit從句)時,才可以把子查詢轉化為join關聯查詢進行優化;

子查詢性能差的原因:

1)子查詢的結果集無法使用索引,通常子查詢的結果集會被存儲到臨時表中,不論是記憶體臨時表還是磁碟臨時表都不會存在索引,所以查詢性能會受到一定的影響;

2)由於子查詢會產生大量的臨時表也沒有索引,所以會消耗過多的CPU和IO資源,產生大量的慢查詢。

7、避免使用JOIN 關聯太多表

1)在Mysql中,對於同一個SQL關聯(join)多個表,每個join 就會多分配一個關聯緩存,如果在一個SQL中關聯的表越多,所占用的記憶體也就越大;

2)如果程式中大量的使用了多表關聯的操作,同時join_buffer_size(MySQL允許關聯緩存的個數)設置的也不合理的情況下,就容易造成伺服器記憶體溢出的情況,就會影響伺服器資料庫性能的穩定性;

3)此外,對於關聯操作來說,會產生臨時表影響查詢效率,而Mysql最多允許關聯61個表,建議不超過5個;

8、對同一列對象進行or 判斷時,使用in 替代or

      in 的值只要涉及不超過500個,則in 操作可以更有效的利用索引,or 大多數情況下很少能利用到索引。

9、禁止使用order by rand() 進行隨機排序

10、禁止在WHERE 從句中對列進行函數轉換和計算

      因為在WHERE 從句中對列進行函數轉換或計算時會導致索引無法使用。

No推薦:

where date(end_time)='20190101'

推薦:

where end_time >= '20190101' and end_time < '20190102'

11、在明顯不會有重覆值時使用UNION ALL 而不是UNION

1)UNION 會把兩個結果集的所有數據放到臨時表中後再進行去重操作;

2)UNION ALL 不會再對結果集進行去重操作;

12、把複雜、較長的SQL 拆分為為多個小SQL 執行

1)大SQL在邏輯上比較複雜,是需要占用大量CPU 進行計算一條SQL語句;

2)在MySQL中,一條SQL 語句只能使用一個CPU 進行計算;

3)SQL拆分後可以通過並行執行來提高處理效率。

六、MySQL資料庫行為規範

1、超過100萬行數據的批量操作(update delete insert),分多次進行

大批量操作可能回造成嚴重的主從延遲;

binlog日誌為row格式時會產生大量的日誌;

避免產生大事物操作。

2、對於大表使用pt-online-schema-change 修改表結構

1)避免大表修改產生的主從延遲、避免在對錶欄位進行修改時進行鎖表;

2)pt-online-schema-change 它首先會建立一個與原表結構相同的新表,並且在新表上進行表結構的修改,然後再把原表中的數據複製到新表中,併在原表中增加一些觸發器;然後,把原表中新增的數據也複製到新表中,在行所有數據複製完成之後,把新表命名成原表,並把原來的表刪除掉,其是把原來一個DDL操作,分解成多個小的批次執行。

3、禁止給程式使用的賬號授予super 許可權

      當達到最大連接數限制時,還運行1個有super許可權的用戶連接super許可權只能留給DBA處理問題的賬號使用。

4、對於程式連接資料庫賬號,遵循許可權最小原則

      程式使用資料庫賬號只能在一個資料庫下使用,且程式使用的賬號原則上不授予drop 許可權。

 

 

 

 

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 在docker中運行第三方服務時,通常需要綁定服務埠到本地主機。但使用 -p 參數進行的埠映射,會自動在iptables中建立規則,繞過firewalld,這對於埠級的黑白名單控制管理是很不利的,所以我們需要對iptables進行手動修改。 這裡以從名為centos.19.09.05的imag ...
  • 什麼是索引? 索引是一種數據結構,具體表現在查找演算法上。 索引目的 提高查詢效率 【類比字典和借書】 如果要查“mysql”這個單詞,我們肯定需要定位到m字母,然後從下往下找到y字母,再找到剩下的sql。如果沒有索引,那麼你可能需要把所有單詞看一遍才能找到你想要的。 去圖書館借書也是一樣,如果你要借 ...
  • 一,設計規範 三大範式 第一範式1NF:屬性不可分【反例:address可1分為國家,省市,地區】 第二範式2NF:屬性完全依賴主鍵 【反例:訂單編號和商品編號位於同一張表中,前者與訂單信息強相關,後者與商品信息強相關】【該拆表了】 第三範式3NF:不允許數據冗餘【兩張表很多屬性相同】 命名規範 1 ...
  • 註意:新版mysql驅動的url必須設置時區,即serverTimezone=UTC,否則會報如下錯誤: ...
  • 排錯-解決MySQL非聚合列未包含在GROUP BY子句報錯問題 By:授客 QQ:1033553122 測試環境 win10 MySQL 5.7 問題描述: 執行類似以下mysql查詢, SELECT id, name, count(*) AS cnt FROM case_table GROUP ...
  • 1.查看mongodb服務是否開啟: ps -ef | grep mongod 2.管理員角色必須在啟用--auth認證參數之前創建,否則會沒有操作許可權。如果之前已經創建過用戶,請先刪除。 kill掉mongod服務,重新啟動,以noauth模式啟動: mongod --dbpath /var/lo ...
  • 1.dos命令 set names gbk; 2.MySQL練習#創建school資料庫: create database school;#切換school資料庫: use school; # primary key : 主鍵約束,不可重覆# auto_increment : 自動增長# not n ...
  • 從bson中導入ObjectId對象,將字元串轉換成id對象查詢使用: ...
一周排行
    -Advertisement-
    Play Games
  • 前言 在我們開發過程中基本上不可或缺的用到一些敏感機密數據,比如SQL伺服器的連接串或者是OAuth2的Secret等,這些敏感數據在代碼中是不太安全的,我們不應該在源代碼中存儲密碼和其他的敏感數據,一種推薦的方式是通過Asp.Net Core的機密管理器。 機密管理器 在 ASP.NET Core ...
  • 新改進提供的Taurus Rpc 功能,可以簡化微服務間的調用,同時可以不用再手動輸出模塊名稱,或調用路徑,包括負載均衡,這一切,由框架實現並提供了。新的Taurus Rpc 功能,將使得服務間的調用,更加輕鬆、簡約、高效。 ...
  • 順序棧的介面程式 目錄順序棧的介面程式頭文件創建順序棧入棧出棧利用棧將10進位轉16進位數驗證 頭文件 #include <stdio.h> #include <stdbool.h> #include <stdlib.h> 創建順序棧 // 指的是順序棧中的元素的數據類型,用戶可以根據需要進行修改 ...
  • 前言 整理這個官方翻譯的系列,原因是網上大部分的 tomcat 版本比較舊,此版本為 v11 最新的版本。 開源項目 從零手寫實現 tomcat minicat 別稱【嗅虎】心有猛虎,輕嗅薔薇。 系列文章 web server apache tomcat11-01-官方文檔入門介紹 web serv ...
  • C總結與剖析:關鍵字篇 -- <<C語言深度解剖>> 目錄C總結與剖析:關鍵字篇 -- <<C語言深度解剖>>程式的本質:二進位文件變數1.變數:記憶體上的某個位置開闢的空間2.變數的初始化3.為什麼要有變數4.局部變數與全局變數5.變數的大小由類型決定6.任何一個變數,記憶體賦值都是從低地址開始往高地 ...
  • 如果讓你來做一個有狀態流式應用的故障恢復,你會如何來做呢? 單機和多機會遇到什麼不同的問題? Flink Checkpoint 是做什麼用的?原理是什麼? ...
  • C++ 多級繼承 多級繼承是一種面向對象編程(OOP)特性,允許一個類從多個基類繼承屬性和方法。它使代碼更易於組織和維護,並促進代碼重用。 多級繼承的語法 在 C++ 中,使用 : 符號來指定繼承關係。多級繼承的語法如下: class DerivedClass : public BaseClass1 ...
  • 前言 什麼是SpringCloud? Spring Cloud 是一系列框架的有序集合,它利用 Spring Boot 的開發便利性簡化了分散式系統的開發,比如服務註冊、服務發現、網關、路由、鏈路追蹤等。Spring Cloud 並不是重覆造輪子,而是將市面上開發得比較好的模塊集成進去,進行封裝,從 ...
  • class_template 類模板和函數模板的定義和使用類似,我們已經進行了介紹。有時,有兩個或多個類,其功能是相同的,僅僅是數據類型不同。類模板用於實現類所需數據的類型參數化 template<class NameType, class AgeType> class Person { publi ...
  • 目錄system v IPC簡介共用記憶體需要用到的函數介面shmget函數--獲取對象IDshmat函數--獲得映射空間shmctl函數--釋放資源共用記憶體實現思路註意 system v IPC簡介 消息隊列、共用記憶體和信號量統稱為system v IPC(進程間通信機制),V是羅馬數字5,是UNI ...